Skip to lesson
‹

Courses / System Design Interview / Chapter 26

Module 3 · Design Real Products · Chapter 26 of 39

Design Nearby Places Search

19 sections · ~35 min✓ Fact-checked

Builds on Back-of-the-Envelope Estimates, Databases: Replication, Partitioning and Choosing a Store, Distributed Caches, Message Queues, Distributed Search and Design Maps and Navigation. Next up: Design a Ride-Sharing App.

Part 1 · Requirements and Scale

The brief

The final over ends at 10:40 pm, and about thirty thousand fans pour out of Chinnaswamy Stadium onto MG Road, hungry. Within minutes, thousands of phones in a few city blocks ask the same app for food nearby. Two things can go wrong. The servers that hold this corner of Bengaluru take ten times their usual load while the rest of the country is quiet. And Priya, standing on MG Road, sees a list of cafés that leaves out the one across the street, 43 m away, because an invisible grid line runs between them. Both problems come from the same question: how does a system turn "near me" into something an index can search?

The product: the search behind "restaurants near me". A user shares their location, picks a category or types a word, and sees nearby places ranked by distance and rating, with filters such as open now. Owners add and edit their listings. Plan for about 200 million places worldwide and the dinner-time peak. One search runs through the chapter: Priya, on MG Road in Bengaluru, looking for cafés within 500 m.

What we are building

Priya's search looks simple, but its core problem is unusual: an ordinary database index cannot answer "what is near this point" efficiently, because nearness depends on two numbers at once. Most of this chapter is about turning a two-dimensional position into something an index can search.

Here is what is in scope today, and what is not:

In scopeOut of scope today
SearchingPlaces within a radius, by category or keyword; filters such as open now and ratingDirections to the place (the maps chapter)
ViewingA place page with hours, photos, rating and review countBooking a table, ordering food
OwnersAdd a place; update hours, phone and photosAds and promoted listings
ReviewsStar ratings and short reviews that feed the place's scoreThe review system in depth

Reviews matter here only as the rating they feed into ranking. The non-functional requirements:

  • Fast: results in under 200 ms at the 99th percentile, including the dinner-time peak.
  • Complete near the user: a café 43 m away, like the one across the street from Priya, must never be missing because a cell border runs between them.
  • Read-heavy: searches outnumber listing updates by hundreds to one.
  • Fresh enough: an owner's new opening hours show up within a few minutes, not instantly.
  • Global: about 200 million places, dense in cities and sparse everywhere else.

How big it gets

The stadium crowd is a local spike; size the global flows first. Assume 200 million places worldwide and 100 million searches a day. Two numbers matter most: the search rate, and the size of the index.

QuantityWorkingResult
Average searches per second100 M ÷ 86,400 s≈ 1,200 /s
Peak searches per secondabout 4× at lunch and dinner≈ 5,000 /s
Listing updates per dayabout 0.1% of places change something≈ 200,000, about 2 a second
Searches per update100 M ÷ 200 K≈ 500 to 1

Searches outnumber edits by about 500 to 1, so the design optimises the read path and lets edits arrive in batches. Now the index. A geo index needs only what the search itself uses: the place id, its position, its cell, and a few fields to filter and rank on. Everything else stays in the database.

Try it first: an index entry holds a place id, its latitude and longitude, its cell and a few ranking fields. How big is the index for 200 M places, and where do the full details live?
  • About 40 bytes an entry: 8 for the id, 16 for the position, 8 for the cell, and 8 for category, rating and flags.
  • 200 M × 40 B ≈ 8 GB: it fits in one server's memory, even if the structure's own overhead doubles it.
  • Full details, about 2 KB a place, come to about 400 GB. They stay in a database and are fetched only for the 20 results on screen.

That number shapes the design: with a minimal index, every search server can hold a full copy of the world, and you add servers for throughput, not capacity. Real indexes carry more per place, such as names and keywords for text search, opening hours and ranking signals. At about 1 KB per place the index is 200 GB, which is usually split into shards by region.

Part 2 · API, Data and the Big Picture

The API

With the flows sized, the calls are few. Priya's search is one read with a position and filters; the rest are ordinary reads and writes.

http
GET   /v1/places/search?lat=12.9755&lng=77.6072&radius=500&category=cafe&open_now=true&limit=20
      -> 200 { places: [{ id, name, lat, lng, distanceM, rating, reviewCount }], nextCursor }
GET   /v1/places/{placeId}                                -> 200 { name, address, hours, photos[] }
POST  /v1/places          { name, lat, lng, category, hours }  -> 202 { placeId, status: "in review" }
PATCH /v1/places/{placeId}       { hours, phone }              -> 202 (visible within minutes)
POST  /v1/places/{placeId}/reviews   { stars, text }           -> 201

Search returns only what the result list shows; the place page loads full details separately.

Changes to places return 202 Accepted because they are not visible at once. A new place may need checking before it appears, since fake listings are a real problem, and changes reach the search index in batches every minute or so, which the requirements allow.

The phone sends its exact position, but the server groups nearby positions for caching, as the caching deep dive explains. Two people standing 30 m apart should usually read the same cached lists.

Cap the radius

Limit radius (say to 20 km) and limit (say to 50). An unbounded radius in a dense city turns one request into a scan of millions of places.

The data model

Behind those calls, the places table is the source of truth. The geo index is a derived copy, rebuilt from it, that holds only what search needs.

placesid (pk)namelatlnggeohashcategoryaddresshoursrating_avgrating_countstatusupdated_at
reviewsid (pk)place_iduser_idstarstextcreated_at
usersid (pk)namecreated_at
ownersuser_id + place_id (pk)roleverified_at

One index entry holds only the fields a search touches:

Field in one index entryBytesWhy it is there
Place id8to fetch details for the winners
Latitude and longitude16exact distance after the cell search
Cell id8the searchable key
Category, rating, flags8filter and rank without a database trip
Total40200 M entries ≈ 8 GB

rating_avg and rating_count are updated as reviews arrive, so ranking never reads the reviews themselves. status lets a place be hidden (closed, under review) without deleting it. Because the index is derived, losing it loses nothing: it can always be rebuilt from the table.

The big picture

Put together, a search runs in three steps: work out which cells cover the search circle (named rectangles on a grid, explained in the first deep dive), ask the geo index shards that own those cells for candidates, then rank them and attach details for the top results. The scene follows Priya's search, and then the crowd behind her:

Animated sceneA search near a shard border0:20

Watch for which shards answer: Priya's nine cells live on only two of them

Read it as steps

Priya's search touches two of three shards; the crowd searching the same cells is answered from the cache.

The search service does the thinking: it turns the circle into cells, merges answers, filters by exact distance and ranks. The shards answer one question only, which places are in these cells, and shard C is never asked. Cells that share a prefix sit together on one shard, so most searches touch one shard and only those near a shard boundary, like Priya's, touch two.

Shard by load, not by area

Split cell ranges so each shard gets a similar share of traffic. A busy city may need several shards to itself, while a large, quiet region shares one.

Part 3 · Deep Dives

From two numbers to one key

Core deep dive

This is the heart of the design: turning a position into one key that an ordinary index can search.

Why can't an ordinary index answer Priya's search? The obvious query is a box: latitude between two values and longitude between two others. With one index on lat and another on lng, the database can narrow the search well with only one of them. The lat index returns a thin strip that runs right round the planet at that latitude, and every row in the strip is then checked for longitude. Some databases can intersect the two indexes, but each one still reads a long strip across the planet.

sql
-- Slow: two ranges on two columns; an ordinary index narrows only one
SELECT id FROM places
WHERE lat BETWEEN 12.9667 AND 12.9847 AND lng BETWEEN 77.5969 AND 77.6153;

-- Fast: one range on one indexed column
SELECT id, lat, lng FROM places WHERE geohash LIKE 'tdr1vf%';

A prefix match on a sorted column is a single range scan.

A geohash is that one key. It names each cell of a grid laid over the world with a short string, and every point inside a cell has a geohash that starts with the cell's name. Each extra character makes the cell smaller:

LengthWidth × height at the equatorRoughly
439 km × 19.5 kma city and its suburbs
54.9 km × 4.9 kma neighbourhood
61.2 km × 0.6 kma few streets
7153 m × 152 ma block
838 m × 19 ma building

Priya's 500 m search will use length 6, as a later page works out. First, how the string is built.

How a geohash is built

A geohash halves the world again and again, alternating between longitude and latitude and starting with longitude: the east half is a 1 and the west half a 0, then the north half a 1 and the south half a 0. Every 5 bits become one character from a 32-character alphabet, 0123456789bcdefghjkmnpqrstuvwxyz: the digits and the letters except a, i, l and o. Here are the first five halvings for a café on MG Road, about 120 m west of Priya, at (12.9757, 77.6061):

BitHalveThe café is inValue
1Longitude, 180° W to 180° Ethe east half, 0° to 180° E1
2Latitude, 90° S to 90° Nthe north half, 0° to 90° N1
3Longitude, 0° to 180° Ethe west half, 0° to 90° E0
4Latitude, 0° to 90° Nthe south half, 0° to 45° N0
5Longitude, 0° to 90° Ethe east half, 45° E to 90° E1
1

HalveLongitude, 180° W to 180° E

The café is inthe east half, 0° to 180° E

Value1

2

HalveLatitude, 90° S to 90° N

The café is inthe north half, 0° to 90° N

Value1

3

HalveLongitude, 0° to 180° E

The café is inthe west half, 0° to 90° E

Value0

4

HalveLatitude, 0° to 90° N

The café is inthe south half, 0° to 45° N

Value0

5

HalveLongitude, 0° to 90° E

The café is inthe east half, 45° E to 90° E

Value1

The bits 11001 make 25, and character 25 of the alphabet, counting from 0, is t. Carry on for 35 bits and the café's geohash is tdr1vfp.

Each extra character splits a cell into 32 smaller ones, which is why a cell's name is a prefix of every geohash inside it: the café's cell is tdr1vf at length 6 and tdr1v at length 5. A café near Cubbon Park, about 1.4 km west, is tdr1vdm: the same 5-character prefix, a different 6th character.

The border problem

Prefixes have one trap: two places can be very close and still share only a short prefix, or none at all, if a cell border runs between them.

Predict before you watch: Priya stands in cell tdr1vf, near its east edge. A café 43 m east has the geohash tdr1y40. Does a search of her own cell find it?
  • No. tdr1y40 lies in cell tdr1y4, which shares only the prefix tdr1 with tdr1vf.
Animated sceneA café across the border0:16

Watch for a café 43 m from Priya that the first search cannot see

Read it as steps

A café 43 m from Priya sits just across a cell border: one cell misses it, nine cells find it.

The miss had nothing to do with distance. Prefixes follow the order of the halvings, so a border can split two close neighbours at a coarse level; the cure is to read the neighbours every time and let exact distance decide.

Here is Priya's cell with its eight neighbours at length 6:

WestCentreEast
Northtdr1vetdr1vgtdr1y5
Middletdr1vdtdr1vftdr1y4
Southtdr1v9tdr1vctdr1y1
North

Westtdr1ve

Centretdr1vg

Easttdr1y5

Middle

Westtdr1vd

Centretdr1vf

Easttdr1y4

South

Westtdr1v9

Centretdr1vc

Easttdr1y1

In the east column, tdr1y4 sits right next to tdr1vf yet shares only tdr1, a cell about 39 km wide. Across the equator or the 0° line of longitude, neighbours share no characters at all, because their very first bits differ.

The standard fix: search the user's cell and its eight neighbours, then filter every candidate by its exact distance (the haversine formula gives the distance between two points on a sphere). Geohash libraries compute the eight neighbouring names for you, and in SQL the block is nine short prefix ranges on the same index.

Choosing the cell size

Nine cells fix the border, but how big should each cell be? For the 3 × 3 block to cover the whole circle wherever the user stands in the centre cell, the cell's shorter side must be at least the radius: the block then reaches at least one full cell beyond the centre cell on every side. That rule picks the cell length for each radius:

RadiusCells to useArea searchedCircle area
100 mlength 7, 3 × 3 block≈ 0.2 km²0.03 km²
500 mlength 6, 3 × 3 block≈ 6.6 km²0.79 km²
2 kmlength 5, 3 × 3 block≈ 214 km²12.6 km²
100 m

Cells to uselength 7, 3 × 3 block

Area searched≈ 0.2 km²

Circle area0.03 km²

500 m

Cells to uselength 6, 3 × 3 block

Area searched≈ 6.6 km²

Circle area0.79 km²

2 km

Cells to uselength 5, 3 × 3 block

Area searched≈ 214 km²

Circle area12.6 km²

Length 6 suits Priya's 500 m: its shorter side is about 610 m, so the block reaches at least 610 m beyond her cell on every side, about 110 m to spare. The spare also absorbs a GPS fix that is a few tens of metres off. A 650 m radius would break the rule and needs length 5, or every length-6 cell the circle touches.

The waste is the price: for 500 m you read about eight times the circle's area. In a dense market area with, say, 1,000 places per square kilometre, that is about 6,600 candidates to keep roughly 800. It works, but it is why dense areas want smaller cells: either search every small cell that touches the circle, or let the cells adapt to density, which leads to quadtrees.

Two more edge cases

In a small town the 3 × 3 block may hold too few places: add the next ring of cells, or drop one character so each cell covers 32 times the area. Away from the equator, cells get narrower east to west, by about 3% in Bengaluru and 12% in Delhi. That does not break the rule for length 6: its height, about 610 m, stays the shorter side anywhere in India. Nearly square length-7 cells shrink to about 134 m wide in Delhi, still above a 100 m radius.

Quadtrees: cells that adapt

Fixed cells waste work where places are crowded: the block around MG Road holds hundreds of cafés, a block in a village almost none. A quadtree starts with one box covering the whole map. Whenever a box holds more than a set number of places, say 100, it splits into four equal quarters, and those split again where needed. Busy city centres end up with tiny boxes and oceans stay as huge ones, so every leaf holds at most 100 places wherever it is. It is the same four-way split as the map tiles in the maps chapter, except that a box splits only where it is crowded.

Finding places near a point in a quadtree
  1. 1Walk downfrom the root, follow the child box that contains the point until you reach a leaf
  2. 2Collecttake the leaf's places: at most 100
  3. 3Widenvisit nearby leaves in order of their distance from the point, adding their places
  4. 4Stoponce you have enough places and every unvisited leaf is farther away than the farthest place you are keeping

Size check: 200 million places at up to 100 per leaf means at least 2 million leaves, plus about a third as many inner nodes. With the 40-byte entries from before, the whole tree is still about 8 to 10 GB. Each search server can build it in memory from the places table, rebuild it nightly, and apply changes in between.

A quadtree also answers "the nearest 20" naturally: it keeps widening until it has enough, with no radius to guess. So which structure should a design start with?

Geohash, quadtree or a library

Both structures can answer Priya's search. They differ in where they live and how they cope with crowded cells:

Geohash gridQuadtree
Cell sizeFixed for a chosen lengthAdapts: small where places are dense
Where it livesA column in any database, with a normal indexAn in-memory structure run by a service
Dense areasMany places per cell, more filteringFew places per leaf
UpdatesChange one row's geohashInsert or move an entry; a full leaf splits
Best forSimple radius search; easy to shard by prefix"Nearest 20" queries over very uneven density

Start with geohash cells, because they work in an ordinary database and shard by prefix. Move to a quadtree when crowded cells such as those around MG Road make fixed cells wasteful, or when "nearest k" becomes the main query. Either way, you add a service to build, rebuild and keep in sync, so the switch should be earned by measured waste.

Names you will hear

S2 and H3 are open-source cell libraries: S2 projects a cube onto the sphere and numbers its square cells along a curve, so nearby cells mostly get nearby ids; H3 uses hexagons, whose six neighbours are all the same distance away, which suits rings and heat maps. R-tree indexes, in databases with spatial support, group nearby shapes into nested boxes and handle lines and areas too. In-memory stores such as Redis offer geo commands built on geohash. Start with your database's spatial index; use an in-memory geo set when points move, and S2 or H3 when several services must share cell ids.

Caching and keeping data fresh

The stadium crowd is the caching problem in one picture: thousands of searches, almost never from exactly the same point. So cache by cell, not by point. Store the candidate list for each cell and category, such as cand:tdr1vf:cafe, for a few minutes. Each search reads nine of these lists, then filters by exact distance and ranks for that user's position, which is cheap.

After the match, the same few dozen cells around MG Road are searched thousands of times a minute, so hit ratios are high. Place details need a cache of their own: at the peak, 5,000 searches a second × 20 results is 100,000 detail lookups a second, far more than the database should serve. Cache details by place id for longer, delete an entry when its place changes, and serve photos from a CDN.

Updating business data is a separate, slower path. Owners and editors write to the places table, after review for sensitive edits. Each change emits an event onto a queue; an index updater applies the events to the geo index in batches every minute, then deletes the affected cached lists and details. A full rebuild from the table runs nightly and repairs any update that was lost.

An owner moves their café to a new address
  1. 1Check the editmoves, closures and name changes may go to review first
  2. 2Update the rownew latitude, longitude and geohash in the places table
  3. 3Emit an event"place 812 moved from tdr1vf to tdr1y4"
  4. 4Apply to the indexremove it from the old cell and add it to the new one in the next batch
  5. 5Drop cached copiesdelete the cached lists for both cells and the place's cached details
Edits can be attacks

Fake listings and false "permanently closed" edits are common abuse on listing sites. Send sensitive edits such as closures, moves and name changes to review, and trust verified owners more than anonymous editors.

Part 4 · Bottlenecks, Failures and Trade-offs

What breaks, and the trade-offs

With the design in place, here is how it fails. Each failure has a planned answer, and each row names what the user sees as well as what the system does.

ProblemEffectResponse
A match ends, or dinner-time in one cityOne shard and its cells get most of the trafficCache candidate lists per cell; add replicas of that shard; split its cell range
All replicas of a shard failPlaces in its cells vanish from resultsReturn the other shards' results marked "partial" rather than an error, and alert
A very dense cellThousands of candidates per searchSmaller cells or a quadtree there; keep each cell's list sorted by popularity
Index updater falls behindChanges take longer than a few minutes to showAlert on lag; the nightly rebuild catches up; owners see "pending"
Position is wrong or roughResults for the wrong areaUse the phone's accuracy value; let the user confirm or pick an area
A zone or a whole region failsSearches served there failSpread every shard's replicas over zones. Each region holds a full copy of the index, which is derived data, so DNS can move users to the next region; edits queue, shown to owners as pending, until the places database's primary returns or a replica is promoted

The derived index is what makes most of these survivable: any copy can be rebuilt from the places table. Three trade-offs run through the design:

  • Bigger vs smaller cells: bigger cells mean fewer lookups but more candidates to filter; smaller cells the reverse.
  • Fixed grid vs quadtree: the grid is simpler and lives in any database; the quadtree adapts to density but is a service you must build and run.
  • Cache lifetime vs freshness: longer lifetimes give more hits, but if a deletion is missed, a 5-minute lifetime can show a stale result for up to 5 minutes, which the requirements allow.

Photos dominate the bill: if 30 million place pages a day each load about 1 MB of photos, the CDN moves about 30 TB a day, while the geo index fits in a few servers' memory.

Part 5 · Going further

Ranking results

Optional: how to rank the candidates once the cells have found them.

Distance alone ranks poorly: the nearest place may be a 2-star café. Rating alone is worse: it sends you across the city. Combine them into one score, for example:

text
closeness = 1 - distance / radius              (1 where you stand, 0 at the edge)
quality   = adjusted_rating / 5
score     = 0.5 × closeness + 0.5 × quality    (plus small boosts: open now, popular)

Example weights. The table below uses a search radius of 1 km.

Adjust ratings for review count. A 5.0 from 4 reviews is weak evidence; a 4.6 from 2,000 is strong. A common fix, a Bayesian average, pretends every place starts with some extra reviews at the site-wide average; with example values of 20 extra reviews at 3.8, adjusted = (20 × 3.8 + reviews × stars) ÷ (20 + reviews). A handful of perfect reviews barely moves the number, while thousands of reviews dominate it.

PlaceDistanceStars (reviews)AdjustedScore
Coffee House A150 m4.0 (900)4.000.82
New Café B300 m5.0 (4)4.000.75
Old Brew C450 m4.6 (2,000)4.590.73
Coffee House A

Distance150 m

Stars (reviews)4.0 (900)

Adjusted4.00

Score0.82

New Café B

Distance300 m

Stars (reviews)5.0 (4)

Adjusted4.00

Score0.75

Old Brew C

Distance450 m

Stars (reviews)4.6 (2,000)

Adjusted4.59

Score0.73

Without the adjustment, New Café B would rank first on its perfect 5.0 (a score of 0.85). With it, B counts as an ordinary 4-star place, and A wins by being closer. The weights, the 20 and the 3.8 are all examples: they are product decisions, tuned by watching which results people actually open.

Keyword searches such as "biryani" combine two indexes: a text index (see the distributed search chapter) finds places whose name, menu or tags match, and the cells limit them to the area. Run the more selective one first. For a common word, take the cells first and match the word within them; for a rare word, find its few matches first and then keep those within the radius.

Rank in two stages

Score every candidate cheaply on the index fields and keep the top 50. Apply anything expensive, such as personal preferences or live opening hours, only to those 50.

Part 6 · Interview kit

The 45-minute answer

A 45-minute slot leaves about 40 minutes of design once introductions and your own questions are done. Here is nearby places search on that clock.

MinutesWhat you say and drawKey number or decision
0–5Requirements: places within a radius by category or keyword, filters, place pages, owner edits. Out of scope: directions, bookings, adsp99 under 200 ms; never miss a place across a border; edits visible within minutes
5–8Only the estimates that decide something: the search rate and the index size≈ 5,000 searches/s at peak; a minimal index of ≈ 8 GB fits on every server
8–13API: one search call with a position, radius and filters; 202 for edits. Data: the places table as the truth, the geo index derived from it40 bytes per index entry; details fetched only for the top 20
13–22The search service turns the circle into cells, asks the geo shards, ranks and fetches details. Edits flow through a queue to the index updaterSplit cell ranges by traffic, not area; cache candidate lists per cell
22–37Core deep dive: why two indexes fail, geohash prefixes, the border problem and the 3 × 3 block, cell size against radius. Then quadtrees for uneven densityA 500 m search uses length-6 cells and reads about 8 times the circle's area
37–40Wrap-up: crowded cells, a lost shard or region, freshness and fake edits; what you would measureReturn partial results rather than an error

Pick the deep dive from the interviewer's question. If they ask how the search finds nearby places at all, go deep on geohash prefixes and the border problem. If they push on dense city centres or "the nearest 20", move to quadtrees. If they ask about load or freshness, cover caching by cell and the edit pipeline.

Say
"I search the user's cell and its eight neighbours, then filter by exact distance: I read about eight times the circle's area, but never miss a place across a border."
Say
"The minimal index is about 8 GB, so every server can hold a copy; once entries carry text and ranking data, I shard by cell prefix, balanced by traffic."
Avoid
"Index latitude and longitude separately and query a box." One index gives you a strip round the planet.

Interview drill

Interviewers change the problem to see whether your design bends or breaks. Try each one before opening the answer.

On New Year's Eve, searches jump to ten times normal for three hours, mostly around Brigade Road and a few other city centres. What do you change?
  • Lean on the cache: the same few hundred cells are searched over and over, so keep candidate lists for about 10 minutes.
  • Add replicas of the hot shards beforehand, and split the hottest cell ranges, balanced by traffic, not area.
  • Protect place details: ten times the peak is about a million detail lookups a second, so cache them longer.
  • If latency still climbs, skip the costly ranking signals and rank by distance and rating.
Add food trucks that move every 30 seconds while they are open. What changes?
  • Places no longer stay put: 30-second moves cannot wait for minute batches and a nightly rebuild.
  • Keep moving places in a separate in-memory geo set, updated by each report and expiring when a truck goes quiet, as the ride-sharing chapter, next, does for drivers.
  • Each search reads the static index and the moving set, then merges them. The load is small: 100,000 trucks every 30 s is about 3,300 updates a second.
A new rule: when an owner marks their place closed for the day, search must stop showing it within 10 seconds. What changes?
  • Minute batches and cached lists both break the rule, so add a fast path for closures only.
  • Write each closure to a small in-memory set of place ids closed today, copied to every search server; every search drops those ids before ranking.
  • Delete the place's cached details at once, and clear the entry at local midnight or when the owner reopens.
Common miss
Searching only the user's own cell. A place 43 m away across a border goes missing; search the 3 × 3 block.
Common miss
Caching results by exact position. No two users stand on the same spot; cache candidate lists per cell.

Wrap-up

Next, Design a Ride-Sharing App runs the same cell search over a million drivers who move every few seconds.

Part 7 · Check yourself

Quick check

Q1After a match, searches around MG Road take 2 seconds, while the rest of Bengaluru stays fast. What is likely wrong, and how do you fix it?

Think it through, then check.

Q2Product changes the search to "the nearest 10 places, whatever the distance", even in a village. How does the query change?

Think it through, then check.

Q3A team of three runs one relational database. Build a quadtree service or use geohash cells? What would change your mind?

Think it through, then check.

Q4A zone outage takes down every replica of the shard holding central Bengaluru at dinner time. What do users see, and what should happen?

Think it through, then check.

Q5Owner edits must reach the geo index and clear stale cached lists without the edit request waiting. Which building block connects them, and why?

Think it through, then check.

Next chapter · 27 of 39Design a Ride-Sharing App~42 min · 2 animated scenes