Requirements
In one line: one of the non-functional requirements is subtly different from its namesake in every other chapter, and noticing the difference is what makes the quadtree inevitable rather than clever.
Functional requirements
| Requirement | Detail |
|---|---|
| User accounts | Users can log in, log out, and manage places' information |
| Search | Users can search for places by name or location (GPS) |
| Feedback | Users can review places using text, images, and ratings |
Search means two different queries wearing one name
"Search for places by name or location (GPS)" bundles two genuinely different operations, and the API lesson will give them separate signatures.
Search by name — "Burger Hut" — is a text lookup. Conventional inverted index, exactly distributed search's problem. The result is one place or a few with matching names.
Search by location — "cafes near me" — is a spatial range query. No text index helps. This is the one that needs a quadtree.
Bundling them under "search" is convenient prose but hides that the system needs two indexes over the same data: one keyed by text, one keyed by position. They are updated together and queried separately.
It also explains a detail in the design that otherwise looks odd. When the quadtree returns results, it returns place IDs — and the system then queries the relational database for names, addresses, and ratings. The spatial index answers "which", the database answers "what". Neither can do the other's job.
Non-functional requirements
| Requirement | Detail |
|---|---|
| High availability | The system must remain accessible to users |
| Scalability | The system must handle fluctuating traffic, including spikes during lunch hours or during tourist seasons |
| Consistency | Users must see a consistent view of place data, reviews, and images |
| Performance | Search results must load with minimal latency |
Scalability here means hotspots, not volume — and that is the whole design
Read the wording carefully, because it is doing more work than it appears to:
"Handle fluctuating traffic, including spikes during lunch hours or during tourist seasons."
Every other chapter defined scalability as more — more users, more data, more requests. This one defines it as uneven, and specifically uneven in space and time together:
- Lunch hours — every restaurant query in a time zone, within a two-hour window.
- Tourist seasons — a specific geographic region carrying a disproportionate share of traffic for months.
Both are hotspots, and hotspots are the recurring adversary of every partitioned system in this course. The Sharded Counters chapter met them as celebrity posts, key-value stores as hot keys, pub-sub as hot partitions.
What makes them worse here is that the partition key is geography, and geography is exactly the dimension along which the load is skewed. If you partition by region and one region gets hot, that partition's servers absorb the entire spike while the rest of the fleet idles. You cannot spread the load because the load is intrinsically local.
Two design decisions follow directly, and both will be justified later by this requirement:
Partition by PlaceID rather than by region — deliberately scattering a hot region's places across many servers, giving up locality to gain load spreading.
Quadtrees sized by place count — so a dense area is many small cells rather than one enormous one, and its load divides naturally.
When the requirement says "fluctuating," the answer is almost never "add capacity." It is "make sure the fluctuation does not concentrate."
Consistency for reviews is weaker than the word suggests
"Users must see a consistent view of place data, reviews, and images."
Taken literally that is a strong promise — and the design does not keep it, for reasons that are entirely defensible but should be said out loud.
The design uses leader-follower replication with followers serving reads, so a review written to the leader is briefly absent from followers. It caches popular places, so a cached entry can be stale. And it updates ratings in the quadtree once a day, so a place's rating in search results can be up to 24 hours behind the reviews that produced it.
None of that is a mistake. It is right for the domain, and the reason is worth stating: nothing here is transactional. A stale review count misleads nobody in a way that matters, and a rating that lags by a day is invisible against the noise of the rating itself.
Compare the payment and inventory systems elsewhere in this course, where reading a stale value causes a double charge or an oversell. The cost of staleness — not the availability of consistency — is what should decide the guarantee, and here the cost is nearly zero.
What the design owes you, then, is honesty about which consistency it means. Read-your-own-writes — a user seeing their own review immediately — is worth engineering and is achievable by routing that user's reads to the leader. Global consistency of everyone's view of a rating is not worth the cost. The evaluation lesson will show the design blurring exactly this distinction.
Availability and performance are conventional here — which is useful information
Nothing unusual is being asked. Availability means replication and no single point of failure; performance means low-latency search.
That is worth noticing rather than skipping, because it tells you these requirements will not be the interesting part of the design. In that building block, latency was the binding constraint that forced precomputation. Here latency is met by the same thing that meets everything else: a good index.
When several requirements collapse into one technique, say so — it is a sign you have found the load-bearing decision rather than a list of them.
Key takeaway
Three functional requirements — accounts, search, feedback — where "search" hides two different queries needing two different indexes: text lookup by name and spatial range query by location. Four non-functional ones, of which scalability is the unusual one: it means hotspots in space and time — lunch hours and tourist seasons — not raw volume. Because the natural partition key is geography and the skew is also geographic, you cannot spread load that is intrinsically local, which is what later forces partitioning by PlaceID and cells sized by place count. And consistency should mean read-your-own-writes, not a global view, because nothing here is transactional.
Next: the estimation, which contradicts itself by a factor of 86,400.