How do you set a policy for which routes run near users and which stay in the data's region, and when do you revisit it?
answer
- the default decides most routes
- promote, do not demote, by exception
- eligibility before latency
- placement is a setting, not a structure
- percentiles by geography, not averages
basics
~20 sDefault every route to the data's region and promote only the ones that answer from the request alone. Keep the choice reversible per route, and re-examine it whenever a route gains a data call or the data moves.
solid answer
~50 sThe default decides most of the outcome, so choose it deliberately: run beside the data, because that is where a route with any reads is fastest, and promote a route near the user only when it earns it. A route earns it by needing nothing but the request, by fitting the constrained runtime the near-user target imposes, and by serving enough traffic per location for anything it caches to stay warm. Make placement a declaration on the route rather than a structural property, so moving it back is a one-line change and a legitimate diagnostic step. Enforce it in review: a near-user route that gains its first data call must be re-placed. Measure by geography at high percentiles, not by a global average. And count the cost honestly — two runtimes means two sets of constraints and two debugging stories, which for a small team can outweigh the milliseconds.
go deeper
What to carry away: placement is chosen per route, and the safe starting point is running beside the data. Routes that need only the request are the ones that move.
Be able to state the promotion criteria — round trips before first byte, runtime eligibility, traffic per location — and why the default should be the conservative one.
Show how you would enforce it in practice: a declaration in the route's own diff, a review trigger when a route gains a read, and per-geography percentile measurement.
Own the whole trade, including the cost of running two runtimes, and be willing to conclude that for this product a single placement is the right answer.
## Start from the default, not the exceptions Most of the latency outcome of an app is decided by which placement is the default, because most routes never get individually considered. The safe default is **the region where the data lives**. It is the placement that is never catastrophically wrong: a route with no reads is only slightly slower there than it would be near the user, while a read-heavy route near the user can be several times slower than it would be in the region. Asymmetric risk argues for the conservative default and a promotion process for the exceptions. The promotion process is what the policy actually is. ## Four questions before a route is promoted 1. **How many round trips does it make before its first byte?** Zero is a clear yes. One is a measurement. Several dependent ones is a no until the route is restructured. 2. **Does its code fit the target?** Near-user execution commonly means a constrained, web-standard-only environment with hard ceilings on CPU, memory and bundle size. A route whose dependency tree assumes a full runtime is not a placement decision at all — it is ineligible until that dependency is replaced. 3. **Is there enough traffic per location?** Anything the route caches or warms is per location. A thin audience spread over many locations keeps each one cold, which can cancel the gain on everything but request-only work. 4. **Can we operate it there?** The near-user runtime has no durable disk and no attachable process, and a page view arrives as several unlinked invocations. If the team cannot yet see into it, only trivially diagnosable work belongs there. | signal | keep it in the data's region | promote it near users | |---|---|---| | data round trips before first byte | one or more, especially dependent | none | | response shape | personalised per user, freshly read | derived from the request alone | | dependency tree | needs a full runtime | web-standard APIs only | | traffic density | thin and scattered | steady in each served geography | | failure cost | high, and needs deep diagnosis | low and self-evident | ## Keep the decision reversible The policy is worth little if acting on it is expensive. Placement should be a declaration attached to a route — a setting the deployment reads — not something the route's structure encodes. Two things follow. First, a wrong decision costs a line and a deploy to undo, which means teams will actually correct them. Second, moving a route back becomes a legitimate diagnostic: same code, same data, one variable changed. The review trigger matters as much as the criteria. The common failure is not a bad initial decision but a silent drift: a request-only handler near the user gains its first data call in an ordinary feature change, and nobody re-asks the question. Make “this route is near the user and now reads data” something a reviewer is expected to notice, and keep the placement declaration close enough to the route that it is visible in the same diff. ## Measure by geography and percentile A global average latency is the worst instrument for this decision: it mixes the users who gained with the users who lost, and near-user placement changes both groups in opposite directions. Judge it by high percentiles per geography, before and after, with the data in its real region. It is normal and acceptable for a promotion to help a distant continent substantially while slightly hurting the users who sat next to the original region — as long as that trade was made knowingly. ## The cost you are actually buying Running two placements is an organisational choice, not only a technical one: - two sets of runtime constraints that library choices must satisfy; - two debugging stories, and engineers who need both; - a build that must produce output for two targets; - a class of bug that appears only in one of them. For an app whose audience is concentrated where its data already is, the honest answer may be that no route should be promoted at all. For a globally distributed audience with meaningful request-only work — routing decisions, variant selection, access gating — the split pays for itself. A lead's job is to make that call explicitly rather than inheriting it from a default. ## When to revisit - The data moved, or gained a second home. - A promoted route acquired a read, or a pinned route lost its last one. - The audience shifted geographically, or traffic density per location changed materially. - The platform's ceilings or runtime changed what is eligible. - An incident showed the diagnosis cost of a near-user route to be higher than assumed.
- How do you keep a placement policy from drifting out of date?Tie it to a review trigger rather than a calendar. A promoted route that gains a data call, a pinned route that loses its last one, and any move of the data itself should each force the question again. Keeping the placement declaration in the route's own diff is what makes a reviewer able to notice.
- When is it right to have no near-user routes at all?When the audience is concentrated near the region that holds the data, or when there is little genuinely request-only work to promote. The gains would be small, and you would still pay the full cost of a second runtime: extra constraints on dependencies, a second build target and a second way for things to fail. A single placement is a legitimate, defensible choice.
- How do you present the trade to stakeholders who only see one latency number?Replace the single number with a per-geography, high-percentile comparison and state plainly who gains and who loses. Near-user placement typically improves distant users substantially and can slightly worsen those next to the original region. That distribution is the decision; an average conceals it.
saying these in an interview costs you the question
- Promotes every route near users because one route got faster
- Sets placement once at project start and never revisits it
- Judges the change by a single global average latency
- Ignores whether the route's dependencies fit the constrained runtime
- Treats placement as architecture rather than a reversible setting
- Counts the milliseconds saved but not the second debugging story