#26 Geo-caching/API Design
Weather Application
Serve current conditions and forecasts for any place to millions of users, while calling the expensive upstream data providers as little as possible.
What is being asked
Design the backend of a weather app. The data comes from a few upstream providers that are slow, rate-limited or paid per call. Users ask for the weather where they are, and many of them are in the same places.
Requirements
Functional
- Current conditions, hourly and daily forecast for a location.
- Search by city; severe-weather alerts.
Non-functional
- Very read-heavy with strong locality: thousands of users per city.
- Data changes slowly, every few minutes at most.
- Must keep answering when a provider is down.
Design
- A request carries coordinates. The API rounds them to a grid cell of a few kilometres, so everyone in a neighbourhood shares one cache key.
- The response for that cell is cached with a lifetime matched to how often each kind of data changes: minutes for current conditions, an hour for the daily forecast.
- Responses are also cacheable at the CDN, so most requests never reach the origin.
- Workers refresh popular cells before they expire, and adapters hide the differences between providers.
Key decisions and trade-offs
- Coarsen the key. Caching per exact coordinate would never hit. Grid cells trade a little precision for a huge hit rate.
- Refresh ahead for hot cells, lazy fetch for rare ones. Pre-fetching every cell on earth would waste provider calls.
- Serve stale on error. If the provider fails, return the last good data with its age rather than an error.
- Stampede protection. When a popular cell expires, only one request should refetch it while the rest wait or get the old value.
Follow-up questions
- How would you push a tornado warning to everyone in an area within seconds?
- How do you combine two providers that disagree?
- How would you keep per-call provider costs under a monthly budget?
- What changes if users want minute-by-minute rain predictions?