Skip to main content
Every execution answers what was decided. Decision Replay answers what would change. Performance Profiling answers the third question: how fast is each rule, right now, on this version? LexQ measures latency continuously in production — no agent, no configuration, on every plan.

How measurement works

Profiling measures only the calls that do not name a version. LexQ sends those to the live version, or some of them to the test version while an A/B test is running. The engine total is the time the engine takes for one request, or for one item of a batch: evaluation and synchronous actions, plus rule loading and compilation on a cache MISS. In a sampled call, LexQ also measures each rule’s condition evaluation time, and the action time of every rule that fired (SELECTED in decisionTraces).
Specific Version Execution calls are billed but never appear in the Performance tab. They are recorded in execution history like any other call. If you select an older version in the Versions list, the tab shows only what was recorded while LexQ was routing calls to it, and only if that period falls inside the selected range.
  • Deterministic sampling. Whether a call is sampled is a pure function of its traceId — anyone can recompute the decision. No randomness, ever.
  • Cache dimension. Executions served from the compiled-rule cache (HIT) and executions that had to load + compile first (MISS — first call, right after a deploy) are kept as separate distributions by design. Mixing them would hide both signals.
  • 60-second windows. Observations aggregate into 60s windows. Missing windows are shown as genuine gaps — never interpolated.
  • Honest percentiles. Every percentile is accompanied by its sample count n. A percentile is shown only when at least 3 observations sit beyond it (n×(1−q) ≥ 3 — p50 from 6, p95 from 60, p99 from 300 samples); otherwise it is withheld (null in the API, – in the console) instead of fabricated.

Slow-rule judgment — relative only

A rule is flagged when its p50 is at least 10× the median of per-rule p50s within the same group, version, phase, and cache state. Judgment requires a cohort of at least 3 rules with n ≥ 100 each. This judgment gate is separate from the per-percentile display gate — a rule can be flagged while its p99 is still withheld. Two deliberate choices:
  1. No absolute thresholds. “Slow” depends on your domain — 50ms may be fine for a batch pipeline and unacceptable for checkout. LexQ never hard-codes a millisecond limit, anywhere.
  2. Median, not mean. With rules at 1, 1, 1, 1 and 40ms, the mean (8.8ms × 10 = 88ms) lets the 40ms rule hide behind the average it inflated. The median (1ms × 10 = 10ms) catches it.

Console

Open a policy group and select the Performance tab. It shows the version selected in the Versions list on the left, which is the live version until you pick another. The Total execution time cards at the top show the engine total for each cache state.
  • Presets 1h / 24h / 7d, a HIT / MISS cache toggle, and per-percentile colors (p50 / p95 / p99) used consistently across cards, tables, and charts.
  • The rule table shows samples, percentiles, the multiple vs. baseline (×1.2), and a Slow badge when flagged.
  • Click a rule for the detail view: a summary per phase × cache state (merged over the window), plus a dot-per-window time series. Dots are raw window values; a gap means those windows have no sample for this rule.

API

2 read endpoints under the partner API (x-api-key auth):
Query parameters (both): versionId (default: live version), from / to (ISO-8601 instants, half-open range [from, to), default: last 24h), and cacheState (HIT | MISS, default HIT, overview only). An empty or inverted range (from ≥ to) returns error P-035. Response semantics worth knowing:
  • A percentile field is null when its display gate (n×(1−q) ≥ 3) is not met; n is always present. Mixed responses — p50 present, p99 null — are normal.
  • baselines[].status is INSUFFICIENT_COHORT until 3 qualifying rules exist.
  • droppedRows counts corrupted histogram rows that were skipped — losses are counted, never hidden.

CLI & MCP

2 MCP tools expose the same data to AI agents: lexq_profile_overview and lexq_profile_rule.

Overhead & retention

Profiling is designed to never compete with your decisions:
  • Measured overhead at the default 1% sampling: +0.12% on engine p50 (JMH, 20-rule fixture). Instrumentation failures are isolated and counted — they never propagate to the decision path.
  • Windows are queryable for 35 days, then archived. Available on every plan.
Per-rule timings come from a 1% sample, so a rule-level percentile needs about 100 times its sample count (see Honest percentiles) in calls within the selected range. Until then it shows –. In a low-traffic group, pick a longer range such as 7d. The engine total is recorded for every Single Group call and every batch item, so its percentiles appear sooner.