The edit that appeared to do nothing
routingTable.conf is hot reloaded — an edit applies within about 200 ms, with no restart. That speed
is exactly why the retained-table case is easy to miss: there is no restart to notice, so “my change
did nothing” is the whole symptom.
What the router does with one message
1
The submission is answered first
The gateway sends
submit_sm_resp, or the REST 200, before routing runs. The customer has
already been told the message was accepted, and charged for it.2
The message goes on the router queue
Accepted work waits here. See Queues and retries.
3
The `default` table is scanned
Rules are tried top to bottom and the first match wins. A rule may send to a vendor, to a
vendor group, or into another table.
4
The chosen worker takes it
The message is enqueued on that vendor’s own queue and leaves at the speed the vendor allows.
cdr_rejected.
Tables are a graph, not a list
A rule whose target names another table chains into it, sodefault → MESSAGE → cheapest is an
ordinary shape. Two things bound the recursion:
A table reached twice by different paths is not a cycle:
default → a → c alongside default → b → c
loads normally.
The two things that load and then quietly misbehave
Both appear on/ops/health under routing_warnings, and each is logged once when it first appears
rather than on every publish.
When messages vanish
Before editing any rule, rule out the three causes that are not routing at all. Only
reason = 'maxAttempts' in cdr_rejected means routing; headerNotApproved, templateNotMatched,
missingMandatoryTlv, insufficientCredit and filtered all mean the message was refused before
routing was reached. See Nothing is delivered.Asking why one message did not match
Next
Writing rules
The four-part grammar, the operators that lie, and vendor groups.
Least-cost routing
Where rule order stops meaning anything.
Filters
Named conditions, and why disabling one narrows a rule to nothing.
Queues and retries
What is already paid for and sitting in memory.