3.1.2.1. Design for Azure Cosmos DB
3.1.2.1. Design for Azure Cosmos DB
💡 First Principle: A globally distributed, multi-model database with tunable consistency provides the foundation for building highly responsive, massively scalable, and resilient applications that serve a worldwide user base with low latency.
Scenario: You are designing a globally distributed mobile gaming application that needs to store real-time player data (scores, achievements). Users expect very low latency regardless of their geographic location. Some data (e.g., high scores) needs to be strongly consistent, while other data (e.g., game progress) can be eventually consistent to optimize performance.
Azure Cosmos DB is Microsoft’s globally distributed, multi-model database service for NoSQL workloads.
Key Design Considerations:
- Consistency Models:
- Strong: Always returns the most recent committed write across all Regions; highest consistency, but increased latency.
- Bounded Staleness: Reads lag behind writes by a set window; balances consistency and performance.
- Session: Guarantees consistency within a single client session; ideal for user-centric scenarios.
- Eventual: Fastest and most available, but data may be temporarily inconsistent across Regions.
- Partitioning:
- Selecting an effective partition key is crucial for distributing data evenly and achieving horizontal scalability. Poor partitioning can cause "hot partitions" and throttling.
- Data Modeling:
- Cosmos DB favors denormalized, embedded document structures to optimize for read performance and minimize cross-partition queries.
- Cost Optimization:
- Throughput is provisioned in Request Units (RUs). Efficient queries, proper indexing, and right-sizing RUs (or using autoscale throughput) help control costs.
Design decisions in practice — the partition key is the decision you cannot undo:
| Decision | Guidance |
|---|---|
| Partition key | Must balance EVEN DISTRIBUTION against the query pattern. A key chosen only for distribution forces cross-partition fan-out on every read; a key matching the most frequent filter keeps queries single-partition and cheap |
| Consistency level | Session is the default and the usual answer: read-your-own-writes from a local replica. Reach for Strong only when a requirement genuinely demands global linearizability, and accept the cross-region latency it costs |
| Throughput | Provisioned for predictable load, autoscale for variable load (it bills for the peak reached within the hour), serverless for spiky development workloads |
| Write topology | Single-region writes with multi-region reads is the simpler default. Multi-region writes add write availability but introduce conflict resolution you must design for |
The five consistency levels are a spectrum, not a quality ranking: Strong, Bounded Staleness, Session, Consistent Prefix, Eventual. Moving down the list trades freshness guarantees for lower latency and lower RU cost — and the correct answer is the weakest level that still satisfies the stated guarantee.
⚠️ Exam Trap: the partition key is fixed for the life of the container. Changing it means creating a new container and migrating the data, which is why a question describing a hot partition is usually testing whether you can spot a bad key rather than asking how to reconfigure one.
⚠️ Common Pitfall: Choosing a poor partition key. A key that doesn't have high cardinality (many unique values) will cause all traffic to hit a single physical partition, creating a "hot partition" that throttles requests and negates the scalability benefits of the service.
Key Trade-Offs:
- Consistency vs. Latency/Availability: Stronger consistency levels in a globally distributed database inherently lead to higher write latency and potentially lower availability during network partitions, as per the CAP theorem.
Reflection Question: How does designing for Azure Cosmos DB, leveraging its global distribution, tunable consistency models, and partitioning strategy, fundamentally enable your application to provide high availability, low latency, and flexible schema for a modern, scalable global application?