Why does a per-request interception step need a matcher, and what does too broad a matcher cost?
answer
- limits who pays for the station
- excluded paths never wake the unit
- early return still costs an invocation
- assets and cached paths are the waste
- too narrow fails open and silently
basics
~10 sThe matcher decides which requests pay for the step. Without one it also runs for static assets and prerendered paths a cache could have answered without waking your code, adding an invocation to each.
solid answer
~50 sThe step sits in front of everything, so the only cheap way to limit its cost is to limit what it sees. A matcher is that instrument: paths it excludes never wake the step's deployment unit at all, which is different from the step running and returning immediately — that still pays an invocation, a possible cold start and the latency floor. Left wide open, the step runs for image, font and script requests and for prerendered paths that the hosting layer could have served from cache directly. Too narrow is the opposite failure: a gate that skips the non-document routes or nested data requests of the same section is trivially routed around. Match the smallest path set for which the rule is actually needed, and re-derive it whenever the rule or the route layout changes.
go deeper
Know that the step does not automatically run for exactly what you want: a matcher declares which paths it applies to, and asset requests should normally be excluded.
Be able to explain why an excluded path is genuinely free while a matched path that returns immediately still pays an invocation, a possible cold start and the latency floor.
Show both failure directions — a wide matcher paying for asset and cached traffic, and a narrow one leaving a section's data paths ungated — and say how you would detect each in production.
Treat the matcher as policy surface: who owns it, how it is reviewed when routes move, and whether a rule expressed as a path pattern is durable enough to be the place the organisation relies on.
## Why a matcher exists at all Per-request interception is defined by its position: it runs before routing, rendering and any cache lookup, for **every** request. Taken literally that includes the ones you never think about — the script, style, image and font requests a single page fans out into, the small icon files browsers ask for unprompted, health checks, and the prerendered paths the hosting layer would otherwise serve straight from a cache. On a busy page the non-document requests outnumber the document request by an order of magnitude, so "every request" is a much bigger bill than it sounds. The **matcher** is the declaration of which paths the step applies to. It is the only cheap instrument available for this, and its cheapness comes from one property worth stating precisely: an excluded path does not invoke the step at all. The unit is not woken, so there is no cold start, no execution time, and on a per-invocation pricing model, no charge. ## Early return is not the same as exclusion A common shortcut is to leave the matcher wide and open the step with a guard that returns immediately for anything uninteresting. That is not equivalent, and the difference is the point of the whole mechanism. | | Excluded by the matcher | Matched, then returns immediately | |---|---|---| | Step invoked | No | Yes | | Cold start possible | No | Yes | | Latency added | None | The station's floor, on every such request | | Per-invocation cost | None | Charged | | Cache-served path still trivially fast | Yes | Your code is now on that path | The guard is still worth writing as a safety net, but it is a second line of defence, not a substitute for narrowing the matcher. ## What too broad costs - **Asset traffic.** Every static file request pays an invocation for a decision that can never apply to it. - **Prerendered and cached paths.** Routes whose whole advantage is being answerable without running application code now run application code first. - **Latency floor everywhere.** The step's own cold path and execution time are added to requests that had nothing to do with the rule. - **Blast radius.** A defect in the step becomes a defect in the delivery of assets and cached pages, not just in the gated section. - **Debugging noise.** Logging in the step buries the interesting requests in sub-resource traffic. ## What too narrow costs The opposite failure is quieter and more dangerous. A matcher written for the visible page paths of a section usually misses: 1. the **non-document routes** in that section — the endpoints the page's own client code calls, which return the same data the page would have shown; 2. the requests a client-side navigation makes for a route's data rather than its HTML, which may use a different path shape than the address bar shows; 3. paths added later under the same section by someone who did not know a matcher enumerated them. Anything the matcher misses simply does not meet the step, so a rule expressed only there is skipped for that traffic. This is one of the concrete reasons a redirect made at this station cannot be the only place a rule is enforced. ## How to choose one 1. Start from the rule, not the routes: which requests would be *wrong* to serve without it? 2. Exclude sub-resource and asset paths explicitly, since they are never that set. 3. Prefer a prefix that covers a whole section over a list of individual pages, so new pages inherit the rule instead of silently escaping it. 4. Ask whether any counterpart data path in the same section needs the same treatment — and whether that treatment belongs here at all rather than in the route. 5. Re-check the matcher whenever the route layout is reorganised; a stale path pattern fails open and says nothing. Meta-frameworks differ in how the selection is expressed — some take path patterns declared alongside the step, some take a configuration entry, some let the step be attached at a level of the route tree so the structure itself is the matcher — but the economics are the same everywhere: what the matcher excludes is free, and what it includes is paid for on every request.
- If the step just returns for asset paths, why narrow the matcher at all?Because the cost is in being invoked, not in what the code then decides. A matched request wakes the step's unit, may pay a cold start, and adds its latency floor before the guard runs. An excluded path skips all of that, so narrowing removes cost that an early return only shortens.
- How does a too-narrow matcher turn into a security problem rather than just a bug?A rule expressed only at this station applies exactly to what the matcher selects. Paths it misses — a section's data endpoints, or pages added later — are served without ever meeting the rule, and nothing reports it. The gate fails open and silently, which is why the real check must also live in the route and in every write.
- What tells you a matcher has quietly gone stale?Traffic patterns: invocation counts that track total requests rather than page views suggest it is too broad, while a section whose pages are served with no trace of the step in logs suggests routes were added outside the pattern. Reviewing the matcher whenever routes are reorganised is cheaper than either discovery.
saying these in an interview costs you the question
- Thinks an early return costs the same as not matching
- Leaves the matcher open and calls it simpler
- Believes asset requests never reach the step
- Enumerates individual pages, so new ones escape the rule
- Treats the matcher as an allow-list that blocks unmatched paths
- Never revisits the matcher after routes are reorganised