# Exercise 2: Design a Layered Scaling Strategy for a Growing Analytics Platform

## Scenario

`MetricPulse` lets customers send custom event data (e.g. "user clicked checkout button") via an API, and view dashboards/charts built from that data. The current architecture is a single stateless API tier (already horizontally scaled, 6 instances) writing directly to a single PostgreSQL database, which both ingests every incoming event AND serves every dashboard query.

MetricPulse just signed 3 large customers, and projects:
- **Write volume** (incoming events) will grow 20x over the next 6 months.
- **Read volume** (dashboard queries) will grow 5x over the same period, and customers increasingly complain dashboards feel slow RIGHT NOW, before any of this new growth even arrives.
- Dashboard queries are read-only and tolerate being up to ~1 minute stale — customers are looking at trends, not needing the literal latest millisecond of data.
- A small but important subset of event-ingestion requests must never be lost, even during a traffic spike — these are billing-relevant events used to invoice customers, and losing one means under-billing a customer.

## Deliverables

Produce all of the following, in this file, below this line:

1. **Address the read-side complaint first** — using theory Sections 3 and 5, propose a combination of read replicas and/or caching for the dashboard-query path, explicitly justified by the "tolerates ~1 minute stale" detail from the scenario. State what specifically you'd cache or replicate, and roughly how you'd decide a cache TTL or replica-lag tolerance given that stated staleness budget.
2. **Address the 20x write-volume growth** — using theory Section 4, explain whether read replicas alone solve this (justify using theory's explicit point about what replicas do and don't scale), and if not, propose a sharding approach for the events table specifically. Name a plausible shard key and explain why it distributes load evenly for THIS workload (many customers, each sending events continuously) rather than creating a hot shard.
3. **Protect the billing-relevant events specifically** — using theory Section 6, propose a queue-based ingestion path for events (or at least for the billing-relevant subset) that decouples "accept the write request" from "durably persist it," and explain concretely how this prevents the "must never be lost during a spike" requirement from depending on the database being able to keep up in real time.
4. **Draw the final layered architecture** as a labeled ASCII diagram (API tier -> queue -> workers -> sharded DB -> read replicas/cache -> dashboards, or your own ordering if you'd arrange it differently) and, in 2-3 sentences, justify the overall shape using theory Section 7's point that these patterns compose rather than being alternatives to each other.

## Constraints

- Deliverable 1's proposal must not silently violate the "never lose billing-relevant events" requirement — clarify explicitly that caching/replica-lag decisions apply to the READ/dashboard path only, not to how writes are persisted.
- Deliverable 2 must explicitly rule out (with a one-sentence reason, referencing theory) any option that only scales reads, since the requirement here is a WRITE volume problem.
