Routing simulator & precedence debugging
Outcome
When a transaction routes to an unexpected partner — or fails to route at all — you can use the precedence simulator to deterministically identify which rule fired (or didn't), why, and what to change.
Prerequisites
| Scope | What it lets you do |
|---|---|
edi.routing.read | Open the simulator |
Familiarity with how routing rules score and tiebreak (3.3 — Submission routing rules).
Where the simulator lives
/routing page → Precedence simulator panel. Backed by
POST /routing/resolve/explain on edi-gateway.
The simulator takes a transaction context as input — not an actual transaction. It is safe to run any time; it never mutates state.
What the simulator returns
The output panel shows:
- Selected rule (the winner) — partner, companion guide,
priority,specificity. - All candidates sorted with
SELECTEDfirst, then by priority ascending, then by specificity descending. - Per candidate,
decisionReason—SELECTED,LOWER_PRIORITY,LOWER_SPECIFICITY,OUT_OF_WINDOW,CAPABILITY_MISSING,SCOPE_MISMATCH, orINACTIVE. - For
SCOPE_MISMATCH, the list ofmismatchedDimensions. - For
CAPABILITY_MISSING, therequiredModeyou asked for plus the partner's declaredpartnerModes.
Common queries
Why is this 837P routing to clearinghouse X instead of state Y?
Inputs:
tx_type:837Pclaim_type:PROFESSIONALdispatch_mode: the mode the consumer used (typicallyBATCH_SFTP)payer_id: state Medicaid (e.g.,OH-MEDICAID)payer_type:MEDICAIDstate:OH
Expected: a state-direct rule should win.
Run the simulator. Outcomes:
| Result | Meaning |
|---|---|
State-direct rule is SELECTED | Working as expected; the misroute happened before the rule existed. Affected transactions need replay. |
Clearinghouse rule is SELECTED because it has a lower priority value | Adjust the state-direct rule's priority below the clearinghouse rule. |
State-direct rule is LOWER_SPECIFICITY | Both rules tied on priority; clearinghouse won the specificity tiebreak. Pin a tighter priority on the state-direct rule. |
State-direct rule is SCOPE_MISMATCH | A condition is excluding it (payer_id, state, or service_line typo). mismatchedDimensions names which. |
State-direct rule is CAPABILITY_MISSING | The target partner has not declared (BATCH_SFTP, 837P). Enable on the partner. |
State-direct rule is OUT_OF_WINDOW | Its effective_from is later than the asOf you supplied. |
Why is no rule firing?
A transaction stuck "no routing rule":
Inputs: same fields the consumer would have populated.
Expected: at least one rule should match.
Outcomes:
| Result | Meaning |
|---|---|
| Several rules show in candidates | The consumer is using slightly different field values; check the source event's enrichment. |
| Zero candidates | No rule for this combination exists. Add one or expand an existing rule's conditions. |
Why does a low-priority "fallback" rule never fire?
Rules with a high priority value (e.g. priority: 200) only fire
when no lower-priority rule survives the filters. When such a fallback
never wins:
- Confirm no other rule with a lower
prioritymatches the same(tx_type, claim_type, dispatch_mode)triple. - Use the simulator's candidate list to see which rule wins instead
and why your fallback is
LOWER_PRIORITY. - Fallback rules are best for "catch-all clearinghouse" or disaster- recovery patterns where you want them to lose to any tighter rule.
Steps to debug a misrouted transaction
Open the misrouted transaction at
/transactions/:id. Note its tx_type, partner, dispatch mode, and timestamp.Open the source claim / event to capture the inputs the routing context had —
claim_type,payer_id,payer_type,state,service_line, the requesteddispatch_mode.Open the simulator → enter those inputs → run. Compare the winner to the actual partner used.
If the simulator agrees with reality — the rules were wrong at the time of submission. Adjust the rules; replay the misrouted transaction.
If the simulator disagrees — a rule changed between submission and now. Look at the rule edit history (audit log) to see what changed. The intervening edit is the cause.
Steps to test a new rule before saving
Compose the new rule in the rule edit form. The simulator panel on the same page accepts a "what-if" mode.
Toggle "Include this draft" in the simulator. The simulator runs as if the draft is already saved.
Run the simulator with several test contexts — your target context and several adjacent contexts (different state, different program). Confirm:
- The rule wins for its target context.
- The rule does not unintentionally win for adjacent contexts.
Save when the simulator confirms expected behavior.
Validation
| Check | Expected |
|---|---|
| Simulator returns within 200 ms | Yes — the resolver is in-memory cached. |
| Per-condition matrix accurately shows match / miss | Yes — verify against your inputs. |
| What-if mode does not persist the draft | Correct — toggling off the draft is enough. |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Simulator returns "no rules in DB" | The rule cache is empty (rare; restart event) | Wait 30s; the cache rebuilds. |
| Simulator winner differs from actual transaction | Rule changed between submission and now | Inspect rule history; adjust as needed. |
| What-if mode stays on after closing the page | Browser session cache | Refresh; the toggle resets. |
| Per-condition matrix shows ✗ on a condition you set | Condition value mismatched (e.g. case sensitivity, leading space) | Re-enter the value; condition matching is exact. |
Next
7.1 — The companion guide editor, or revisit Getting Started any time a new teammate joins.