Context
Internal teams needed consistent access to product and operational data. Direct database access worked initially, but query duplication and schema coupling made even small changes risky.
Constraints
- Existing reporting workflows could not stop during migration.
- Freshness requirements varied by dataset.
- Some analytical queries were too expensive for synchronous execution.
Architecture
A typed HTTP API exposes domain-level resources backed by curated database views. Frequently requested aggregates are refreshed on a schedule, while small queries execute against indexed read models. Every response declares its data freshness.
Technical decisions
- Defined response contracts around business concepts rather than table structure.
- Added query budgets and pagination to protect shared infrastructure.
- Instrumented slow queries with traces that link API spans to database operations.
- Used expand-and-contract migrations to keep consumers compatible.
Trade-offs
Pre-aggregation introduces controlled staleness. The API makes that trade-off visible rather than implying that every metric is real time.
Outcome
Consumers gain a stable interface, and schema evolution becomes a backend concern instead of a coordinated change across every internal tool.