Cosmos DB Interview Questions and Answers (2026)
Cosmos DB interview questions center on a few concepts that are easy to misunderstand — partition key selection, the RU cost model, and consistency levels — since getting them wrong shows up as real production throttling. Here are the ones that come up most.
-
What is a partition key and why does choosing it well matter so much?
The partition key determines how Cosmos DB physically distributes data across logical and physical partitions to enable horizontal scale. Every logical partition (all items sharing the same partition key value) is capped at 20GB of storage, and throughput (RU/s) is spread across physical partitions, so a poorly chosen key creates "hot partitions" where one value receives disproportionate traffic while others sit idle, wasting provisioned RUs and causing throttling (429s) on the hot one. A good partition key has high cardinality (many distinct values), spreads read/write load evenly, and — critically — aligns with your most common query filter, since queries that include the partition key are routed to a single partition and are far cheaper than fan-out queries across all partitions. Example: for a multi-tenant app,
tenantIdis often a strong partition key if tenants are numerous and roughly balanced in size and traffic. -
Describe the five consistency levels and their tradeoffs.
From strongest to weakest: Strong guarantees linearizability — reads always return the most recent committed write, but at the cost of higher latency and reduced availability during regional failover, and it's unavailable across multi-region writes. Bounded Staleness guarantees reads lag writes by at most K versions or T time, giving predictable staleness bounds with better latency than Strong. Session (the default) guarantees read-your-own-writes and monotonic reads within a single client session via a session token, offering a strong practical guarantee for the common case of a user reading their own updates, with low latency. Consistent Prefix guarantees you never see out-of-order writes (no gaps), but may see stale data. Eventual gives no ordering guarantee at all beyond eventual convergence, offering the lowest latency and highest availability/throughput. Most production apps default to Session as the sweet spot; Strong is reserved for cases like financial ledgers where staleness is unacceptable.
-
Explain the Request Unit (RU) model.
An RU is Cosmos DB's abstraction for normalized cost across CPU, memory, and IOPS needed to perform an operation — a 1KB point read of a single item by ID and partition key costs roughly 1 RU as a baseline, while writes, complex queries, and larger items cost proportionally more. You provision throughput as RU/s (either manually or via autoscale), and every request consumes from that budget; exceeding it returns a 429 (Too Many Requests) with a retry-after hint, which SDKs typically handle automatically. RU cost is influenced by item size, indexing policy (more indexed properties = more RUs on write), query complexity (cross-partition queries, ORDER BY, aggregates all add cost), and consistency level (Strong/Bounded Staleness cost more due to replication guarantees). Understanding RU cost lets you predict and control spend — you can inspect actual RU charge per request via the
x-ms-request-chargeresponse header. -
What's the difference between provisioning throughput at the database level vs the container level?
Database-level (shared) throughput provisions a pool of RU/s shared across all containers in that database (up to 25 containers by default), which is cost-effective for many low-traffic containers since idle containers don't waste dedicated capacity — but any single container can be starved if others consume the shared pool, and there's no per-container isolation or SLA guarantee. Container-level (dedicated) throughput provisions RU/s exclusively for one container, guaranteeing it always has its provisioned capacity regardless of what other containers are doing, which is the right choice for high-traffic or SLA-critical containers. A common real-world pattern: use dedicated throughput for your few high-traffic, business-critical containers, and shared database throughput for a long tail of low-traffic auxiliary containers (e.g., config or lookup tables) to reduce overall cost.
-
What is the Change Feed and what is it used for?
Change Feed is a persistent, ordered log of changes (inserts and updates, not deletes by default) made to items within a container, similar in spirit to a database trigger or CDC stream, exposed per logical partition and processed via the Change Feed Processor library or integrated Azure Functions trigger. It's commonly used for event-driven architectures — triggering downstream processing when data changes — materializing views/read models in another store, real-time analytics pipelines, cache invalidation, or replicating a subset of data into another system (e.g., syncing to Synapse or Elasticsearch). Because deletes aren't captured by default, a common pattern for soft-delete tracking is adding a
isDeletedflag and TTL rather than a hard delete, or using the newer "all versions and deletes" change feed mode. Consumers checkpoint their position so processing can resume from where it left off after a restart. -
How does the indexing policy work, and how would you tune it for cost/performance?
By default, Cosmos DB automatically indexes every property of every item, which is convenient but means every property indexed adds write RU cost and storage overhead — often unnecessary for large or deeply nested documents. You can customize the indexing policy to include only paths you actually query on and exclude the rest (commonly excluding large blob-like or rarely-queried subtrees with a wildcard):
{ "indexingMode": "consistent", "includedPaths": [{ "path": "/status/?" }, { "path": "/customerId/?" }], "excludedPaths": [{ "path": "/*" }] }This flips the model to include-only, reducing write RU cost significantly for write-heavy containers with large documents. Composite indexes are also worth adding explicitly when you have queries with
ORDER BYon multiple properties or equality+range filters together, since single-property indexes alone won't serve those efficiently. -
When would you choose Cosmos DB over a relational database like SQL Server?
Cosmos DB fits when you need guaranteed low single-digit-millisecond latency at any scale, elastic horizontal scale-out with no downtime, multi-region active-active writes, or a flexible/evolving schema (semi-structured JSON documents) — common in IoT telemetry, personalization/catalog data, gaming leaderboards, and globally distributed SaaS applications. A relational database remains the better choice when your data is genuinely relational with complex multi-table joins and transactional integrity across many entities (Cosmos DB transactions are scoped to a single logical partition), when you need strong ad-hoc query flexibility with arbitrary joins/aggregations, or when the team's expertise and tooling (reporting, BI) are built around SQL and the scale doesn't demand global distribution. Cost is also a factor — Cosmos DB's RU-based pricing can exceed a well-sized relational database for moderate, single-region workloads.
-
Explain global distribution and multi-region writes in Cosmos DB.
Cosmos DB lets you associate a database account with any number of Azure regions with a few clicks/API calls, and it handles data replication transparently — no application-level replication logic needed. In single-region-write (multi-region-read) mode, one region is designated as the write region while others serve low-latency local reads, with automatic or manual failover if the write region goes down. In multi-region-write mode, every region can accept writes simultaneously, giving the lowest possible write latency globally, with conflict resolution handled via last-writer-wins (based on a timestamp or custom property) by default, or a custom conflict resolution stored procedure for more complex merge logic. Multi-region writes are powerful but require the application to accept eventual convergence and potentially tolerate/resolve conflicts — it's not compatible with Strong consistency, which requires a single write region.
-
What are the different Cosmos DB APIs and why would you pick a non-native one?
Cosmos DB exposes multiple wire-protocol-compatible APIs on the same underlying engine: the native SQL/Core (NoSQL) API with a SQL-like query language over JSON documents; MongoDB API for apps that speak the MongoDB wire protocol; Cassandra API for CQL-based workloads; Gremlin API for graph traversal queries; and Table API as a scale/feature upgrade path from Azure Table Storage. You'd choose a non-native API primarily for migration scenarios — lifting an existing MongoDB or Cassandra application into Azure with minimal code changes while gaining Cosmos DB's global distribution, SLAs, and elastic scale — rather than starting fresh. For new development, the native SQL/Core API is generally recommended since it exposes the full feature set (most complete query capabilities, latest features land there first) without any protocol-translation overhead or feature gaps.
-
What's the cost difference between a point read and a query, and why does it matter?
A point read fetches a single item by its unique
idand partition key value directly, which is the cheapest possible operation — typically around 1 RU for a 1KB item — because Cosmos DB can route directly to the exact physical partition and item without any query engine involvement. A query, even one that filters down to a single matching item, invokes the query engine (parsing, potentially scanning an index, evaluating predicates) and costs meaningfully more RUs for equivalent results, and if it's not scoped to a partition key it fans out across all physical partitions, multiplying cost further. The practical implication: whenever your access pattern is "get this exact item by ID," always use a point read (ReadItemAsyncin the SDK) rather than aSELECT * WHERE id = @idquery — it's a simple, high-leverage optimization frequently missed by teams new to Cosmos DB. -
What is TTL (Time to Live) and how is it configured?
TTL lets Cosmos DB automatically delete items after a specified period, useful for session data, caches, logs, or any data with a natural expiration without needing a manual cleanup job. It's configured at the container level (
DefaultTimeToLive, in seconds) and can be overridden per item via attlproperty on the document itself — a value of -1 on an item means it never expires even if the container has a default, and omittingttlon an item while the container default is unset means the item persists indefinitely. Example: set containerDefaultTimeToLiveto 86400 (1 day) for a session-tracking container so any item without its ownttloverride expires 24 hours after last modification. Expired items are deleted by a background process (not instantly at the exact TTL second) and this deletion consumes background RUs, so very high TTL churn should be factored into throughput sizing. -
How does optimistic concurrency control work with ETags in Cosmos DB?
Every item in Cosmos DB has a system-generated
_etagproperty that changes whenever the item is updated. Optimistic concurrency uses this: when updating an item, you pass the_etagvalue you last read as anIf-Matchprecondition (viaAccessCondition/ItemRequestOptions.IfMatchEtagin the SDK); if another process modified the item in between, the ETag won't match and the server rejects the write with a 412 Precondition Failed, letting the client re-read the latest version, reapply its change, and retry rather than silently overwriting someone else's update. This avoids the overhead of pessimistic locking while still preventing lost updates in concurrent-write scenarios, which is important since Cosmos DB has no native multi-item locking mechanism. It's the standard pattern for read-modify-write flows, e.g., decrementing inventory count safely when multiple requests might race on the same item.
Practicing for a real interview? Get live AI help with your answers, in the browser, free to start.
Start a free session