System designby Learnastra

System-design interview · Extended interviews

Design maps and route planning

By Anup Rai

Model road and turn transitions, calculate shortest paths, version traffic and shortcuts, and scale routing separately from map tiles.

You will learn to

  • Calculate shortest paths on a directed weighted road graph.
  • Separate tile delivery, endpoint snapping, route search, and ETA.
  • Explain versioned topology/traffic and cross-region search failure behavior.

Practice in this chapter

8 interview questions with model answers and follow-ups.

Go to interview practice

Useful foundations: Design nearby place search and friend discovery · Database indexes: B-trees, composite keys and query access · Caching: cache hits, misses, write policies and invalidation · Data partitioning and sharding

Workload and timing examples are interview assumptions.

01Problem and scope

A routing service finds legal paths using the selected road graph, travel profile and traffic version. Displaying the map is a separate job: delivering map tiles. In the example, A-B-D costs 4+4=8 minutes and A-C-D costs 3+8=11. The route follows legal roads with the lowest travel-time cost, which may differ from the shortest geometric path. Its estimated duration is not a guaranteed arrival time.

Represent intersections as vertices and directed roads as edges with nonnegative travel-time costs. One-way restrictions remove reverse movements. Turns may need extra state recording the incoming road. On one server, store the graph and run a shortest-path algorithm; only then discuss regional distribution.

I clarify whether the interviewer means drawing a map, computing a route, or navigating a moving driver. We build map display and point-to-point driving routes for departure now, with an optional navigation session that refreshes after incidents. We do not claim the private design of a named map provider.

The product question is “fastest under the selected road and traffic model,” not “guaranteed arrival at exactly this time.” Traffic estimates can be wrong. Access restrictions and known closures, however, are hard constraints in that selected model. The route client should not be sent across a forbidden edge merely because its geometric path is shorter.

I ask about geographic scope and choose a large country with regional deployments and cross-region routes. That makes boundary routing and consistent map versions concrete requirements without pretending every street fits on one tiny server.

02Functional requirements

  1. View a map. Versioned tiles for a bounding box and zoom.
  2. Request directions. Legal road sequence, geometry, duration, distance, and data versions.
  3. Avoid tolls. Search the permitted profile or clearly report no route.
  4. Start away from a road. Snap to an accessible candidate within a bounded radius.
  5. Refresh after an incident. Recompute under a newer compatible traffic/closure bundle.
  6. Request a matrix. Bounded origin/destination set with explicit resource limits.

Scope and acceptance boundaries

Support background map tiles, driving directions, distance, estimated arrival time, avoid-toll preferences, and known closures. Geocoding addresses, transit schedules, offline routing, and lane guidance are separate extensions. State whether departure is now or a future time; future-time costs require stronger modeling than a single current-speed snapshot.

A tile is a visual map fragment, not the routing graph. Snapping connects a GPS point to plausible accessible roads. Map matching interprets a sequence of noisy GPS observations. Routing engines expose these operations separately; OSRM is one documented implementation. OSRM API.

A no-route result differs from a snapping failure. A point may have no plausible accessible road, or two valid snapped points may be disconnected under current restrictions. Those conditions receive separate codes and user guidance.

An alternative-route feature promises a small set of meaningfully different valid candidates, not every possible path. We keep it optional because finding diversity and ranking alternatives requires more work than one shortest-path result. Geometry simplification for display must not change the underlying legal road sequence used for directions.

03Non-functional requirements

  1. Workload. Assume ten million route requests/day and a 2,000/s peak.
  2. Latency. Target route p95 below 300 ms for ordinary regional trips and tile p95 below 100 ms from a nearby edge cache.
  3. Availability. Target 99.9% routing availability. The sample algorithms do not supply this objective automatically.
  4. Update freshness. Publish validated topology daily, normally refresh traffic weights within one minute, and target trusted urgent-closure ingestion within ten seconds.
  5. Version consistency. Use one compatible immutable bundle of topology, turn restrictions, weights and acceleration structures. Return its versions and traffic freshness.
  6. Closure validation. Before returning a route, check its roads and turns against the closure data available at final validation, then return that data's version and the validation time.

Safe degradation

Missing or invalid input Permitted response
Current traffic unavailable Use labeled historical weights while preserving known access restrictions
Invalid topology or incompatible artifacts Fail or fall back to a verified base search
New closure after response Notify active navigation sessions to recompute

An older estimate can still describe one consistent road model. Mixing versions can instead pair shortcuts with costs or roads that no longer match. Never invent a route to meet uptime. No service can guarantee knowledge of an unreported physical incident; an already returned route can be invalidated by a newly reported closure.

04Capacity estimates

Quantity Calculation Consequence
Route requests 10M/day / 86,400 ≈ 116/s average Design for separate peaks
CPU at assumed peak 2,000 queries/s × 0.05 CPU-s = 100 cores Before redundancy/headroom
Tile reads 1B/day / 86,400 ≈ 11,574/s CDN delivery dominates reads
Raw edge metadata 100M directed edges × 32 B = 3.2 GB Geometry/turn data/indexes add much more

The 50-millisecond CPU cost is a benchmark assumption, not an engine guarantee. Long rural/interregional routes may explore more graph than short city trips. Cache immutable tile versions separately from short-lived traffic-sensitive route results.

With a 60% planned CPU utilization ceiling, the assumed 100 cores of route work implies about 167 cores before redundancy. Surviving the loss of one of three equally sized zones while maintaining that utilization would require more reserved capacity. A worker may reach its memory-bandwidth limit first, especially if the search repeatedly fetches graph data that is not nearby in memory.

At an illustrative 20 KB route response, 2,000 routes/s yields 40 MB/s of response payload. Tile traffic is different: one billion 30 KB tiles/day is 30 TB/day, about 347 MB/s average, before peaks. A CDN is therefore justified by repeated immutable map content even if route computation stays regional.

A 100-by-100 travel-time matrix contains 10,000 pairs. A specialized many-to-many algorithm can reuse work, but the request is not equivalent to one route. Cap matrix dimensions and use estimated work, rather than HTTP request count, when deciding how many matrices to admit.

Version retention multiplies graph memory or disk. Three simultaneously loaded 3.2 GB raw edge sets require 9.6 GB before geometry, turns, shortcuts, indexes, and worker overhead. Retain only the bundles needed for active queries, rollback, and the declared replay window, with explicit query pins: records that prevent cleanup from deleting a graph bundle while a query is using it.

05APIs and contracts

Route request and response

POST /routes accepts {requestId:"q61",origin:[lon,lat],destination:[lon,lat],mode:"car",avoidTolls:true,departure:"now"}. The response includes snapped endpoints, durationSeconds=480, distanceMeters, turn steps, geometry, bundleId, closureVersion, and trafficObservedThrough. A retry is a fresh computation unless a client explicitly requests the same retained bundle; route calculation itself has no financial side effect requiring a persistent idempotency ledger.

Distinct error outcomes

Invalid coordinates, unsupported profiles, excessive matrix size, no accessible segment, and no connecting route are distinct errors. Returning straight-line distance as a driving route would misrepresent the product. If a matrix offers a fallback estimate, each such cell must be flagged as estimated rather than a valid road path.

Tile and route-cache identities

Tile URLs include style and immutable map version as well as zoom/x/y. Route-cache identity includes profile, snapped endpoints, avoidance preferences, departure assumptions, and compatible bundle version. Rounding endpoints too much can move them across a divided road or onto an overpass. Any cache-key simplification must preserve the chosen road connection.

Navigation session and privacy

A navigation session supplies a route ID, current location, and last accepted closure version. Position updates are authenticated and short-lived. They are not exposed through public cache keys or reused as another user's raw trace.

06Data model and access patterns

Store both the actual road connections and the built data structures that speed up search. A shortcut is a search edge summarizing an existing path; it must retain enough information to expand back into those roads. It does not create a new legal road connection. The bundle manifest identifies the road, turn, weight and shortcut versions built to work together; publication checks that they are compatible.

Record Material fields Use
Directed edge edgeId, from, to, geometry, access classes Legal road movement
Turn rule incomingEdge, outgoingEdge, profile, restriction/cost Prohibit or penalize specific turns
Weight edgeId, version, travel time, observation age Travel-time cost used in this bundle
Snap index spatial cell, accessible edge candidates Attach coordinates to plausible roads
Shortcut endpoints, expanded path, cost, compatibility version Faster search that expands back to real roads
Bundle manifest topology, turns, weights, shortcuts, checksums Atomic compatible release
Closure overlay affected edge/turn, version, effective interval Hard access constraint
Tile object map/style version, zoom, x, y Cacheable visual display

Raw map edits and consent-based observations are source inputs. Built routing graphs and tiles are derived artifacts. The bundle manifest is authoritative for which compatible artifacts are serving. A traffic update referencing removed edge IDs cannot be blindly applied to a new topology; builders map or reject incompatible observations before publication.

Location histories receive a separate short retention and access policy from public road geometry. Aggregated traffic should not allow a route query to retrieve an individual driver's trace.

A snapped point may lie partway along a road edge. Add temporary directed connectors or split that edge for the query. Use proportional or model-derived travel costs, while keeping its turn and access restrictions. On a one-way 1,000 m segment, an origin 200 m from its start and destination 900 m from its start imply a 700 m forward traversal, not a full 1,000 m edge or an illegal reverse shortcut. Candidate snapping also needs a bounded search policy: selecting one plausible candidate is not proof of the best route across all plausible candidates.

07Basic working design

The first server loads a directed, turn-aware graph and its spatial index into memory. For q61 it validates the car profile, chooses accessible snap candidates near A and D, and runs Dijkstra under fixed nonnegative travel-time weights. It relaxes tentative distances by checking whether each explored edge gives a cheaper known path, saving the predecessor edge whenever it does. When D is settled—its minimum cost is established—the server follows those saved edges backward to reconstruct the route.

In the example graph, A→C initially looks promising at three minutes, but its continuation to D costs eight, producing eleven total. A→B takes four and B→D four, so that path wins at eight. The server returns the real edge sequence, turn instructions, geometry, and the pinned data version. Map tiles can be served as simple static files separately.

This baseline supports a legitimate small routing product. It has no distributed graph transaction and no need to move a query between servers. A map refresh builds a second immutable graph and switches a local pointer only after validation, allowing in-flight queries to finish on their old version.

We deliberately begin with correct base search. Accelerating an incorrect access model only returns illegal answers faster. Turn restrictions, one-way roads, and unreachable endpoints are tested before adding hierarchy shortcuts or regional sharding.

architecture · baselineOne graph, one shortest-path search

The graph is turn-aware and pinned for the request; tiles are a separate display artifact.

One graph, one shortest-path searchThe graph is turn-aware and pinned for the request; tiles are a separate display artifact. client to api: q61: A to D, car; api to graph: Snap and search fixed weights; api to client: A–B–D / eight-minute estimate; client to tiles: Load visual map tilesq61: A to D, carSnap and search fixed weightsA–B–D / eight-minute estimateLoad visual map tilesACTORMap clientSERVICERoute applicationSTOREDirected graph +snap indexSTOREStatic tile objectssync
Read each connection in order
  1. syncq61: A to D, carMap client → Route application
  2. syncSnap and search fixed weightsRoute application → Directed graph + snap index
  3. syncA–B–D / eight-minute estimateRoute application → Map client
  4. syncLoad visual map tilesMap client → Static tile objects

08Find the baseline flaws

At the assumed peak, fifty milliseconds of CPU per query consumes one hundred cores. A single worker cannot provide that compute, and long interregional paths may explore far more state than the average. Map tiles additionally create repeated bandwidth load unrelated to route CPU. Separate tile bandwidth from route computation when sizing servers.

A correctness failure appears when a worker uses a shortcut A→D with cost 8 built from A→B→D, while a live update closes B→D. If it treats the shortcut as an independent legal road, it still returns eight minutes through a forbidden segment. The acceleration structure must be compatible with changed constraints or the query must fall back to a method that checks them correctly.

Another failure comes from naive regional partitioning. The fastest valid route between two points inside region X may leave X and reenter. Searching only X or selecting the nearest border misses valid candidates. Regional boundaries are deployment choices, not road-access restrictions.

Finally, a nearest geometric snap can place the route client on a motorway above a local street without an accessible ramp. Directions then begin with an impossible movement. Snapping uses mode, direction, road access, and a bounded set of candidates, not only Euclidean distance.

09Improve the design, step by step

The baseline already finds a valid shortest path; the scaling question is how to examine less graph or spread independent queries across machines. For the shortest-path guarantee used here, A* guides exploration with an estimate no greater than the remaining cost. Preprocessed methods instead build reusable path summaries before requests arrive. Those are different ways to reduce search work, with different update costs.

Approach Strength Cost
Base Dijkstra/A* Clear flexible search Expensive large explorations
Preprocessed shortcuts Faster long paths Preprocessing/version compatibility
Regional graph shards Smaller worker state Boundary routing and crossings
Historical time profiles Stable estimates with sparse observations Miss current incidents

A routing hierarchy summarizes known subpaths as shortcuts with valid costs. If weights or restrictions change, update the affected shortcut data or use a search that does not rely on it. For regional shards, an overlay records connecting border routes; a valid path may leave and reenter a region. Do not assume one boundary crossing or blindly choose the nearest border. Bound matrix sizes because n origins×m destinations can multiply work far beyond one query.

First, split immutable tile delivery from route computation. The trigger is high repeated tile bandwidth. Put versioned tiles behind edge caches while route servers compute personalized paths. This reduces origin load and improves map rendering, at the cost of cache storage and style/version lifecycle. Direct static serving remains sufficient for a small geographic product. Tile freshness does not determine traffic-weight freshness.

Second, replicate in-memory routing workers. The trigger is the 100-core peak estimate. A region-aware router sends queries to warmed workers with a compatible graph bundle already loaded. This increases parallel route throughput without changing shortest-path semantics. Each replica needs graph memory and time to load it. A new worker must check checksums and bundle compatibility before accepting requests. One larger server is simpler while measured demand fits comfortably.

Third, preprocess a valid acceleration structure. The trigger is long-route search CPU. Shortcuts or hierarchical methods summarize subpaths while retaining expansion information and compatibility requirements. The search may examine far fewer edges, but building, storing and updating shortcuts takes extra work. A base Dijkstra/A* fallback remains useful for unusual profiles or changed restrictions that invalidate shortcuts. We do not assume every hierarchy supports arbitrary dynamic weights without rebuilding.

Fourth, partition very large graphs with a compatible overlay. The trigger is a bundle too large or expensive to replicate everywhere. Regional workers handle local detail while a border overlay represents valid interregional connections and costs under the same release. Each worker stores less graph data, but workers must coordinate how a route crosses their boundaries. The overlay must permit repeated region crossings, and its selected route must expand into valid local subpaths. Full-graph replicas remain preferable when affordable because they avoid these distributed boundary concerns.

Each optimization is accepted only after comparison with a trusted base search on representative and adversarial routes. Faster average latency is not evidence that the new routing method still respects restrictions.

10Detailed architecture

Validated build pipeline

The final system has a data pipeline and a serving path. Map editors and trusted feeds supply topology and restriction updates. A traffic pipeline validates and aggregates consent-based observations. Build workers produce compatible graph, turn, weight, shortcut, and snap artifacts, test them, and register immutable bundles. A manifest authority switches the active bundle only after the required serving regions can load it.

Tile and route serving

Clients fetch tiles from a CDN backed by immutable tile objects. Route requests instead pass through authentication and admission, then a regional query router. Warm routing workers pin one manifest bundle, use a graph cache or local memory, perform search, expand shortcuts, validate closure constraints, and return the versioned result. The route cache key includes all request choices that affect the path, plus the bundle version.

Urgent closures

Trusted urgent closures enter a versioned overlay and invalidate affected cached routes or trigger navigation recomputation under the stated freshness policy. Check that the overlay’s edge IDs and expanded shortcuts belong to the selected graph; closure data cannot be applied to an arbitrary graph version.

Artifact lifetime and implementation

Builds, traffic aggregation, tile generation, and deployment are asynchronous. Query routing, snapping, search, and final validation are synchronous. Old artifacts remain pinned for active queries and rollback. A cleanup transaction cannot mark an artifact deleting while a serving manifest or valid query pin references it; publication rejects deleting artifacts. This makes retention safe even during a release race.

OSRM offers a concrete build/serve option with extraction plus either contraction-hierarchy preprocessing or multi-level partition/customization. Select the pipeline for update frequency and supported profiles, then verify its update capabilities against the one-minute traffic objective. PostgreSQL with PostGIS/pgRouting is useful for smaller graphs, spatial preprocessing and a reference shortest-path implementation. Neither product name automatically supplies this chapter’s bundle publication, urgent-closure boundary or arbitrary per-request restriction support; those contracts must be verified in the selected deployment.

architecture · finalVersioned builds and warmed routing replicas

Query workers pin compatible artifacts; traffic builds and tile delivery follow separate paths.

Versioned builds and warmed routing replicasQuery workers pin compatible artifacts; traffic builds and tile delivery follow separate paths. client to cdn: Load versioned visual tiles; cdn to tile: Cache miss; client to api: 1. q61 route / preferences; api to worker: 2. Admit and route query; worker to manifest: 3. Pin compatible bundle; worker to graph: 4. Snap / search / expand path; worker to cache: Read / write exact version key; worker to closure: 5. Final closure validation; maps to build: Topology and turn updates; obs to traffic: Observed positions / times; traffic to build: Version-compatible weights; build to graph: Upload tested immutable artifacts; build to manifest: Publish ready compatible bundle; build to tile: Build immutable visual tiles; maps to closure: Trusted urgent closuresLoad versioned visual tilesCache miss1. q61 route / preferences2. Admit and route query3. Pin compatible bundle4. Snap / search / expand pathRead / write exact version key5. Final closure validationTopology and turn updatesObserved positions / timesVersion-compatible weightsUpload tested immutableartifactsPublish ready compatiblebundleBuild immutable visual tilesTrusted urgent closuresACTORMap / navigationclientsG1CACHETile CDNG1STOREImmutable tileobjectsG1SERVICERoute auth /admission routerG2SERVICEWarm regionalrouting workersG2CACHEVersionedroute-result cacheG2STOREBundle manifest +query pinsG3STOREGraph / turns /weights / shortcutsG3WORKERValidated graph buildworkersG4EXTERNALTrusted map andrestriction feedsG4EXTERNALConsent-basedobservationsG4WORKERTraffic matching /aggregationG4STORETrusted closureoverlayG3syncasyncG1 Clients and visual deliveryG2 Route servingG3 Serving data authorityG4 Data ingestion and builds
Read each connection in order
  1. syncLoad versioned visual tilesMap / navigation clients → Tile CDN
  2. syncCache missTile CDN → Immutable tile objects
  3. sync1. q61 route / preferencesMap / navigation clients → Route auth / admission router
  4. sync2. Admit and route queryRoute auth / admission router → Warm regional routing workers
  5. sync3. Pin compatible bundleWarm regional routing workers → Bundle manifest + query pins
  6. sync4. Snap / search / expand pathWarm regional routing workers → Graph / turns / weights / shortcuts
  7. syncRead / write exact version keyWarm regional routing workers → Versioned route-result cache
  8. sync5. Final closure validationWarm regional routing workers → Trusted closure overlay
  9. asyncTopology and turn updatesTrusted map and restriction feeds → Validated graph build workers
  10. asyncObserved positions / timesConsent-based observations → Traffic matching / aggregation
  11. asyncVersion-compatible weightsTraffic matching / aggregation → Validated graph build workers
  12. syncUpload tested immutable artifactsValidated graph build workers → Graph / turns / weights / shortcuts
  13. syncPublish ready compatible bundleValidated graph build workers → Bundle manifest + query pins
  14. asyncBuild immutable visual tilesValidated graph build workers → Immutable tile objects
  15. asyncTrusted urgent closuresTrusted map and restriction feeds → Trusted closure overlay

11Write path and acknowledgement

Topology, restrictions and traffic changes produce tested compatible artifacts. Activate a version only when the required serving workers can use the complete bundle.

GPS observations collected with consent are noisy. Use movement and direction to match a sequence to roads, reject implausible samples, aggregate speeds over time, and supplement sparse observations with historical profiles. Do not expose raw traces through route caches. Known closures remain access constraints even when live-speed updates fail.

Publish topology builds after connectivity/restriction checks and sample-route tests; switch a version manifest atomically. Keep older compatible snapshots for in-flight queries and rollback. For future departures, evaluate time-dependent edge costs at arrival to each edge. Algorithms require explicit assumptions, such as whether leaving an edge later can ever produce earlier arrival; do not reuse a static proof without those conditions.

  1. Each accepted observation records where it came from, when it occurred and which location use was permitted. The pipeline rejects impossible jumps and stale or malformed samples before aggregation.
  2. Map matching associates a sequence with plausible directed edges under a known topology. One isolated noisy point does not establish a vehicle's road or speed.
  3. Aggregation estimates travel time and confidence for each edge, using historical profiles when there are too few reliable samples. Trusted closure events remain hard restrictions rather than inferred low speeds.
  4. A build or customization job creates a candidate bundle g12/w9 with compatible turns and shortcut data. It runs connectivity, access, expansion, and sample-route comparisons against a verified reference.
  5. Workers stage and checksum the immutable artifacts. The manifest authority atomically publishes the compatible bundle and its serving policy, while retaining references for active old-version queries.
  6. Cache entries keyed to w8 are no longer selected as w9 results. Active navigation may receive a refresh notice. A failed publication leaves the previous manifest intact; uploaded candidate artifacts alone never make a release live.

The relevant time-dependent condition is called FIFO, for first in, first out: entering the same edge later cannot produce an earlier arrival at its end. This matters because a shortest-path search must know whether arriving sooner can ever be worse than arriving later. The algorithm section returns to the precise condition and what changes when waiting can help.

For departure in the future, an edge's cost depends on when the path reaches it. The static eight-minute example does not prove correctness for arbitrary non-FIFO time-dependent travel, so that extension requires a matching algorithm and explicit waiting assumptions.

12Read and delivery path

Each route keeps one compatible graph, weight set and profile while it runs. It connects endpoints to accessible roads and expands shortcuts into the actual road sequence.

API/record Example
Route POST /routes {requestId:q61,origin:...,destination:...,mode:car,avoidTolls:true,departure:now}
Edge r2: B→D,costMinutes=4,allowedCar=true,graph=g12
Snapshot (topology=g12,weights=w8,profile=car)
Matrix extension Bounded origins×destinations → travel times
  1. q61 validates locations/profile and pins g12/w8.
  2. The snap index finds accessible candidates A and D; nearby overpass geometry alone cannot imply access.
  3. Search evaluates A-B-D=8 and A-C-D=11 under those versions.
  4. Expand any shortcut edges into actual roads, then construct turn steps and geometry.
  5. Return the eight-minute estimate with freshness/version context; tiles load independently.

Include profile, endpoints, preferences, departure assumptions, and graph/weight versions in route-cache identity.

  1. The worker checks the expanded edge and turn sequence against the closure version at its final validation boundary. If a newly known closure invalidates B→D, it recomputes or returns a retryable update condition according to the latency budget; it does not return a route whose actual expanded path fails the selected constraints.
  2. It returns the bundle, validation time, traffic freshness, estimate confidence and any fallback used. The route client can distinguish current observed traffic from historical estimation.
  3. The query releases its artifact pin after response construction. A navigation session retains route identity and listens for relevant incident changes; it does not keep the entire old graph version alive indefinitely merely because the user has not closed the app.

A cache hit still obeys closure freshness policy. The cache key protects against accidental version mixing, but an urgent incident may deliberately invalidate an otherwise valid older cache entry. The routing product must choose that policy explicitly rather than assuming a short TTL makes every cached route safe.

13Correctness deep dive

Dijkstra repeatedly settles the unsettled vertex with the smallest known accumulated cost. From A, tentative B=4 and C=3. Settle C first: D becomes 11. Settle B next: D improves to 8. Then settling D establishes the eight-minute route for this nonnegative-cost graph. pgRouting’s Dijkstra explanation.

Concept in focusDijkstra settles the smallest tentative distance first

All edge weights in this example are nonnegative and fixed for the query. Greedily following the first cheap edge would miss the best complete route.

Dijkstra settles the smallest tentative distance firstAll edge weights in this example are nonnegative and fixed for the query. Greedily following the first cheap edge would miss the best complete route. Directed edges cost A-B=4, A-C=3, B-D=4 and C-D=8 minutes. Settle C first at 3 and discover a tentative route to D of 11. Settle B at 4 and improve D to 8. Settle D at 8; the best route is A-B-D.4 min3 min4 min8 minABCDDijkstra settles C at 3, then B at 4, then D at 8. Settling C first does notcommit the whole route through C.Best route: A -> B -> D = 8 minutes. Alternative A -> C -> D = 11minutes. Edge costs are nonnegative.

Remember: Choose the smallest tentative distance; update routes through that node.

Read the diagram
  1. Directed edges cost A-B=4, A-C=3, B-D=4 and C-D=8 minutes.
  2. Settle C first at 3 and discover a tentative route to D of 11.
  3. Settle B at 4 and improve D to 8.
  4. Settle D at 8; the best route is A-B-D.

A* adds a lower bound for remaining cost to guide exploration. Straight-line distance divided by a genuine maximum possible speed can be admissible; an arbitrary ETA guess may not be. If optimality is promised, pruning must preserve it. Road closures represent forbidden edges, not merely a tiny speed penalty.

The key algorithm invariant is that, with nonnegative costs, the smallest unsettled tentative distance cannot be improved through a later unsettled vertex. In the example, settling C at 3 produces D11; settling B at 4 improves D8; D is then settled at 8. Choosing C greedily and committing its entire path at the first step would be wrong. A* may guide the queue with a lower bound, but its exact correctness conditions still matter.

Publication can also race a query. Query Q must select its graph bundle as one unit while publisher P switches the active bundle:

beginRoute():
  transactionally read active bundle B
  require B status == ready and artifacts not deleting
  acquire query pin on B
  return immutable B

publish(candidate C):
  verify compatible topology/turns/weights/shortcuts
  require all artifacts ready and not deleting
  atomically change active bundle to C with references
Ordering Q's interpretation Result
Q pins g12/w8 before publication Entire search uses old compatible bundle Eight minutes, unless final closure validation requires refresh
P publishes g12/w9 before Q pins Entire search excludes B→D A→C→D, eleven minutes
Q observes a newer closure at final validation Existing path is rejected if affected Recompute or explicitly retry

For a time-dependent edge, FIFO means departing later cannot produce an earlier arrival on that edge: t + travelTime(t) is nondecreasing. Under the appropriate FIFO assumptions, a label-setting time-dependent search can remain valid. If FIFO does not hold, waiting may improve arrival and the algorithm/state model must represent that possibility; a static Dijkstra implementation cannot simply read changing costs mid-search.

sequence · bundle-switchA query never mixes two releases

The old query retains its coherent bundle; final closure validation can require recomputation.

A query never mixes two releasesThe old query retains its coherent bundle; final closure validation can require recomputation. q to m: Pin ready g12/w8; m to q: Return artifact references; p to m: Publish compatible g12/w9; q to q: Search w8: A–B–D cost 8; q to c: Validate expanded path / closure version; c to q: B–D now prohibited; q to m: Pin new compatible bundle; q to q: Recompute A–C–D cost 11; q to m: Release old query pinPARTICIPANTRouting worker QPARTICIPANTManifest authorityPARTICIPANTBundle publisher PPARTICIPANTClosure authority1. Pin ready g12/w82. Return artifact references3. Publish compatible g12/w94. Search w8: A–B–D cost85. Validate expanded path / closure version6. B–D now prohibited7. Pin new compatible bundle8. Recompute A–C–D cost119. Release old query pinsyncreturn
Read each connection in order
  1. syncPin ready g12/w8Routing worker Q → Manifest authority
  2. returnReturn artifact referencesManifest authority → Routing worker Q
  3. syncPublish compatible g12/w9Bundle publisher P → Manifest authority
  4. syncSearch w8: A–B–D cost 8Routing worker Q → Routing worker Q
  5. syncValidate expanded path / closure versionRouting worker Q → Closure authority
  6. returnB–D now prohibitedClosure authority → Routing worker Q
  7. syncPin new compatible bundleRouting worker Q → Manifest authority
  8. syncRecompute A–C–D cost 11Routing worker Q → Routing worker Q
  9. syncRelease old query pinRouting worker Q → Manifest authority

14Failure and recovery

Failure or race Required response and boundary
Closure changes during a query While q61 uses g12/w8, an incident creates closure version w9 removing B→D. If final closure validation observes that restriction, the running query must recompute or return an explicit retry/degraded outcome; it cannot return the now-forbidden path just because its bundle was pinned earlier. A closure published after the stated validation boundary can instead invalidate an already authorized response or active route. Never mix half of w8 with half of w9. The next query on w9 selects A-C-D=11 if permitted. Urgent closures may warrant invalidating cached routes and notifying active navigation sessions.
Traffic/topology unavailable When traffic is unavailable, label historical ETA; when topology cannot connect endpoints, return no route rather than fabricate one. Monitor snapping distance, no-route rate, route p99, ETA error, traffic age, graph-build failures, and cross-region regressions. Restrict access to user locations and minimize raw trace retention.
Query or build crash; bad release A worker crash loses only an in-flight computation; the client can retry and may receive a newer bundle. A build worker crash leaves staged artifacts that are not serving until manifest publication. An invalid release is rolled back by changing the active manifest to a retained compatible bundle, while a trusted closure overlay still enforces known restrictions under its defined compatibility rules.
Control-plane partition During a control-plane partition, warmed workers may continue under a bounded cached-manifest policy for ordinary routes. If urgent closure freshness exceeds the permitted age, the service reports degraded freshness or refuses affected safety-sensitive requests rather than claiming current knowledge. A region without the required graph or overlay cannot fabricate a cross-region path.
Expensive-query overload During overload, cap expensive alternatives and matrix dimensions, queue only within the latency budget, and reserve capacity for active-navigation reroutes. Serving a stale historical ETA may be acceptable if labeled; serving a path through a known prohibited edge is a different failure and not an equivalent fallback.

15Operations, security, and cost

Location data is sensitive. Authenticate navigation sessions, minimize raw trace retention, aggregate traffic, and restrict access to individual coordinates. Public tiles can be broadly cached, but personalized origin/destination pairs should not leak through shared logs or cache inspection. Trusted closure feeds require provenance and auditability so an unverified report cannot block an entire city automatically.

Track route p95/p99 by distance and region, snap distance, no-route rate, expanded-path restriction violations, traffic age, ETA error, and candidate-bundle validation failures. Compare ETA to completed trips with awareness of selection bias and detours; an aggregate error metric alone can conceal severe underestimation on one region or road class.

Before publication, test one-way streets, turn prohibitions, overpasses, disconnected islands, toll avoidance, border exits/reentries, and shortcut expansion after a closure. Run copies of representative queries against the candidate, previous release and a trusted base search, then compare their results without returning the candidate's answers to users yet. A canary rollout pins a fraction of traffic to the candidate and permits immediate manifest rollback.

At 167 assumed compute cores before redundancy, reducing mean CPU from 50 ms to 20 ms would reduce the same 2,000/s work from 100 to 40 core-seconds/s. That benefit must be weighed against preprocessing time and memory. If a traffic update requires rebuilding for ten minutes, a faster query engine may fail the one-minute freshness objective. Measure both sides of the tradeoff.

16Decision ledger and limitations

Decision Benefit Cost and change trigger
Immutable compatible bundles Reproducible search and safe rollback Retained artifacts; rebuild when compatibility changes
Base search fallback Flexible correctness reference More CPU on long paths
Preprocessed shortcuts Fast long-distance queries Build/customization complexity and version coupling
Regional graph plus overlay Each worker stores less graph data Must preserve valid border crossings; regional calls add latency
CDN tiles Cheap repeated map display Separate visual-version lifecycle
Historical traffic fallback Routes remain available with sparse observations Less current ETA; freshness must be visible

Start by replicating full regional bundles. Fetching individual graph vertices from remote servers would add many network waits and make the route depend on more servers staying available. When graph size forces partitioning, an overlay summarizes cross-boundary work instead of making every edge relaxation a network request.

The remaining limit is the accuracy and timeliness of input data. More cores cannot infer an unreported closure, and a mathematically shortest path under inaccurate travel times may not be fastest in reality. The product therefore returns estimates and freshness while preserving legal constraints in its known model.

Future departures, transit, and offline navigation are substantial extensions. Each changes the time model, access model, or update availability and deserves a fresh requirement discussion.

17Interview closing

“I separated map tiles from route computation. A route is a shortest legal path under the chosen cost model in a directed, turn-aware graph. I begin with a correct nonnegative-cost search and accessible endpoint snapping, then scale tiles through a CDN and route work through warmed replicas. Add precomputed shortcuts only when their versions match and they can be expanded back into valid roads.

“The hard serving guarantee is one coherent graph bundle per query. Topology, turns, weights, and shortcuts are pinned together, with final closure validation under a stated version. A release cannot make one query mix old shortcut costs and new restrictions. A route affected by a newly enforced closure must be recomputed against a compatible bundle before release, rather than retaining an invalid shortcut. Already returned routes can be refreshed through navigation notices.

“The tradeoffs are preprocessing versus freshness, graph memory versus regional boundaries, and current traffic versus labeled historical estimates. I would benchmark long and cross-border routes and test closures, overpasses, and turn prohibitions before optimizing average latency. The next measurement is whether query CPU or update-to-serving delay limits the product.”

If the interviewer adds future departures, I would use time-dependent costs evaluated at arrival to each edge and verify the relevant FIFO or waiting assumptions. The static proof would not be reused unchanged.

Practise the interview questions

Say your answer aloud before opening the model answer. Then answer the follow-up and compare the reasoning.

Foundation · Question 1

Edges A→B and B→D each cost four minutes; A→C costs three and C→D eight. Which legal route from A to D is faster?

Reveal a model answer

The legal directed edge costs sum to eight minutes for A-B-D and eleven for A-C-D. The optimization target is travel time, not the number of roads or visual distance. I would explicitly include one-way/access and turn rules in the graph representation.

What the answer must demonstrate: Calculate a legal path under the chosen cost.

Applied · Question 2

Why does A* need an admissible heuristic?

Reveal a model answer

When I promise the optimal path, the heuristic must be a lower bound. In graph search I also use a consistent heuristic if closed states are never reopened, or reopen states when an admissible but inconsistent heuristic discovers a better path. Straight-line distance divided by a genuine maximum speed can provide a lower bound; an arbitrary learned ETA can overestimate.

What the answer must demonstrate: Connect algorithm assumptions to the promised result.

Foundation · Question 3

Why not snap the route client to the geometrically nearest road?

Reveal a model answer

GPS can be near an overpass, fenced road, or wrong carriageway without a legal connection. I consider road accessibility, direction, and plausible endpoint candidates. For a GPS sequence, movement context helps choose the correct road rather than processing every point independently.

What the answer must demonstrate: Define adjacent location operations distinctly.

Applied · Question 4

Traffic changes while a route search is exploring its graph. Which versions should the request read?

Reveal a model answer

Keep one compatible graph-and-weight snapshot throughout the search, or deliberately restart on a newer one. Arbitrarily mixing changing values makes the route cost difficult to interpret and can invalidate preprocessed shortcuts. The response should state the freshness assumptions used for its estimate.

What the answer must demonstrate: Version consistency and safety refresh policy are both needed.

Follow-up · Question 5

Can a cross-country route be composed from the nearest region exits?

Reveal a model answer

Not reliably. The nearest exit locally can lead to a much longer global route, and a valid path may reenter a region. I need an overlay that represents interregion connectivity and correct shortcut costs, then search that structure under the selected profile.

What the answer must demonstrate: Local greediness does not prove global route quality.

Follow-up · Question 6

How does tomorrow at 8 a.m. differ from leaving now?

Reveal a model answer

The cost of each edge depends on when the route client reaches it, so one frozen current-speed value per edge is insufficient. I need historical/time-dependent functions and an algorithm whose assumptions match those functions, then label the forecast uncertainty.

What the answer must demonstrate: Future departure is a modeling change, not just another timestamp field.

Applied · Question 7

A traffic release arrives halfway through a query. What prevents mixed weights and shortcuts?

Reveal a model answer

The query pins one immutable compatible bundle at admission. Publication switches a manifest, not individual arrays. The query either completes under that bundle or restarts under a newer one when the closure policy requires it. Artifact pins prevent cleanup while it runs.

What the answer must demonstrate: Distinguish internal consistency from perfect real-world knowledge.

Follow-up · Question 8

Why can a 100-by-100 matrix overload a service with a low request count?

Reveal a model answer

It asks for ten thousand origin-destination relationships. Specialized algorithms may reuse work, but the workload is much larger than one route. I bound dimensions, estimate work, and use separate admission or asynchronous execution for large matrices.

What the answer must demonstrate: Count internal work, not only endpoint calls.

Blank-page exercise · 45 minutes

Build the answer yourself

Find a route from A to D across two alternatives. Scale map tiles separately, then close B→D mid-query and extend the request to a future departure time.

  • Calculate both route costs by hand.
  • Distinguish geocoding, snapping, matching, tiles, and routing.
  • Estimate CPU and tile/graph payloads separately.
  • Pin coherent versions and explain shortcut validity.
  • Handle closures, regional boundaries, and future-time assumptions.

Check that each component and design decision follows from your requirements and workload.

Recall the key ideas

Answer from memory before opening each card. Explain why the choice works and what it costs. Revisit missed cards tomorrow.

Design maps and route planningWhat is a road graph?Recall first, then reveal

Vertices represent positions/states; directed edges represent legal movements with costs such as travel time.

Connections + direction + cost.

Return to lesson
Design maps and route planningWhat makes an A* heuristic safe?Recall first, then reveal

It must not overestimate the remaining cost when optimality is promised.

Lower bound, not a hopeful guess.

Return to lesson
Design maps and route planningWhy pin graph and traffic versions?Recall first, then reveal

A route’s edges, restrictions, and costs must describe one compatible view while the query runs.

One query, coherent road rules.

Return to lesson

Final revision

Summary and interview notes

Routing finds a legal shortest path under a specified directed graph, turn model and cost version. Tiles, endpoint snapping, route search and traffic estimation scale differently. Keeping each query on one compatible version of the graph, restrictions, weights and shortcuts prevents updates from mixing incompatible route calculations.

Remember these points

  • Record legal directions and the road used to enter an intersection, so nearby roads are not mistaken for valid turns.
  • Dijkstra requires nonnegative included costs; A* needs a valid heuristic and appropriate reopen/consistency rules.
  • For endpoints partway along a road, preserve legal travel direction and charge only the cost of the part traveled.
  • Pin topology, turns, weights and shortcuts together; expand and validate against the stated closure boundary.
  • Traffic estimates can be stale or wrong even when the computed path is optimal for its model.

Interview tips

  • Compute the two route costs by hand before discussing hierarchy or sharding.
  • Test overpasses, one-way roads, prohibited turns and regional exit/reentry against base search.
  • Separate query CPU, tile bandwidth and update-to-serving delay in the capacity discussion.

Important qualifications

  • Future-departure routing requires time-dependent FIFO or explicit waiting assumptions.
  • Engine preprocessing and supported dynamic updates vary; the custom publication contract is not implied by selecting OSRM or pgRouting.

Technical references

  • OSRM API documentationPrimary descriptions of route, nearest, table, and match operations in a routing implementation.
  • pgRouting Dijkstra documentationVersioned primary Dijkstra cost API reference. The worked graph uses nonnegative travel costs; this link is not a claim about the newest pgRouting release.
  • OSRM backend documentationOfficial extraction, MLD partition/customization and CH contraction pipelines; benchmark update compatibility rather than assuming arbitrary dynamic restrictions.

Practice marks stay in this browser.