In this post we are going to cover request units, throughput and cost in Azure Cosmos DB. These are 7 real Cosmos DB interview questions for data engineers, asked the way they come up on a real project, and the last one is a scenario: Cosmos DB costs doubled this month, finance wants answers, and you find where to look and what to change.
A request unit is how Cosmos DB measures and bills work. Every read, write and query costs a number of request units, and we either buy a budget of them per second or pay for what we consume. Interviewers ask about this because it's where performance and cost meet: throttling, sizing, autoscale and the monthly bill all come back to request units.
Part 3 of the Real Time Azure Cosmos DB Interview Questions and Answers series on TechBrothersIT.
- The short answer
- Let's set up the project
- Question 1: Your manager asks what a request unit is. How do you explain it?
- Question 2: A teammate sees 429 errors during a load. What does throttling mean, and how should the client handle it?
- Question 3: Someone asks how to measure the RU cost of a read, a write and a query. How do you find it?
- Question 4: The team must choose between database-level and container-level throughput. How do you decide?
- Question 5: Traffic is quiet at night and busy during the day. How do autoscale and serverless change the bill?
- Question 6: A teammate asks why a write costs more than a point read. What drives the RU charge?
- Scenario 7: Cosmos DB costs doubled this month and finance wants answers. Where do you look and what do you change?
- The full script
The short answer
A request unit is the one currency for CPU, IO and memory: a 1 KB point read is 1 RU, writes and queries cost more. You buy RU/s (manual or autoscale, per database or per container) or pay per RU on serverless; past the budget, requests get 429 and the SDK retries.
Let's set up the project
We run the official Azure Cosmos DB Linux emulator locally, and small Python scripts that use the azure-cosmos client, so every output is real. Features the emulator doesn't support are shown as code. One thing to know up front: the emulator charges 1 request unit for everything and never throttles, so every request unit number in this post comes from Microsoft's documentation for Azure. common.py just creates the client from the COSMOS_ENDPOINT and COSMOS_KEY environment variables.
import os
from azure.cosmos import CosmosClient
client = CosmosClient(os.environ["COSMOS_ENDPOINT"],
credential=os.environ["COSMOS_KEY"])Question 1: Your manager asks what a request unit is. How do you explain it?
A request unit, or RU, is the performance currency of Cosmos DB. Every read, write or query costs a number of request units: one number for the CPU, the IO and the memory it used.
- CPU - processing
- IO - input / output operations
- Memory - working set
- Request units - one charge per operation
Let's look at the baseline Microsoft documents for Azure:
| Documented (Azure) | RU |
|---|---|
| point read, 1 KB item | 1 |
| point read, 100 KB item | 10 |
| same operation, same data | same RU every time |
| provisioned RU/s | a budget per second |
| serverless | pay per RU consumed |
So a point read of a 1 KB item is 1 RU, and a point read of a 100 KB item costs 10.
And it's deterministic. The same operation on the same data costs the same RUs every time, so we measure it once and plan with it.
Then there are two ways to pay. Provisioned throughput buys request units per second, a budget that resets every second. Serverless bills the request units we actually consume.
In a multi-region account, the RU/s we provision are there, and billed, in each region.
Question 2: A teammate sees 429 errors during a load. What does throttling mean, and how should the client handle it?
A 429 means request rate too large. In that second, the requests needed more request units than the container, or one hot partition, has. The budget resets every second, so a 429 means slow down and retry, not an outage.
Here's the flow:
- Request - needs more RU/s
- 429 - rate limited
- SDK waits - x-ms-retry-after-ms
- Retry - up to 9 times, 30 s
The Python SDK already retries for us. Let's read the settings from the client config. retry_config.py builds a default client and a tuned one with retry_total=5 and retry_backoff_max=15, then prints the retry options of each. We run python retry_config.py.
import os
from azure.cosmos import CosmosClient
URL, KEY = os.environ["COSMOS_ENDPOINT"], os.environ["COSMOS_KEY"]
clients = {
"default": CosmosClient(URL, credential=KEY),
"tuned": CosmosClient(URL, credential=KEY,
retry_total=5, retry_backoff_max=15),
}
for name, c in clients.items():
r = c.client_connection.connection_policy.RetryOptions
print(f"{name:8} max_retries={r.MaxRetryAttemptCount}",
f"max_wait_s={r.MaxWaitTimeInSeconds}",
f"fixed_interval_ms={r.FixedRetryIntervalInMilliseconds}")$ python retry_config.py
default max_retries=9 max_wait_s=30 fixed_interval_ms=None
tuned max_retries=5 max_wait_s=15 fixed_interval_ms=NoneThe default client shows max_retries=9 max_wait_s=30, and the tuned one max_retries=5 max_wait_s=15. Between tries, the SDK waits what the service sends in the retry-after header.
| Python SDK, 429 retries | Default |
|---|---|
| retry attempts | 9 (retry_total) |
| total wait | 30 s (retry_backoff_max) |
| wait between tries | the service's retry-after |
| then | CosmosHttpResponseError 429 |
Only when the retries run out does our code get the error, with status 429. The emulator never throttles, so the handling is shown as code. In a bulk load, we catch the 429, re-queue the document and slow down, instead of failing the whole job.
# Azure behavior, not run: the emulator never returns 429
import time
from azure.cosmos.exceptions import CosmosHttpResponseError
def load(container, docs, retry_later):
for doc in docs:
try:
container.upsert_item(doc) # SDK retries 429s first
except CosmosHttpResponseError as e:
if e.status_code != 429:
raise
retry_later.append(doc) # re-queue, do not fail
time.sleep(5) # and slow downMicrosoft calls 1 to 5 percent 429s, with acceptable latency, a healthy sign. Many more means more throughput, or a better partition key.
Question 3: Someone asks how to measure the RU cost of a read, a write and a query. How do you find it?
Every response carries its charge in a header, x-ms-request-charge. We read it in code, so measuring is cheap and exact.
Let's do all three in one script. charge.py writes an order, and the returned item's get_response_headers() has the charge. The read uses the client's last_response_headers, as Microsoft's docs do, which is fine in one thread. The query result has get_response_headers() too, and we also pass a response_hook that sees each page. We run python charge.py.
from azure.cosmos import PartitionKey
from common import client
db = client.create_database_if_not_exists("shop")
orders = db.create_container_if_not_exists(
"orders", partition_key=PartitionKey(path="/customerId"))
HDR = "x-ms-request-charge"
def show(op, headers):
print(f"{op:6} {HDR} in headers: {HDR in headers}")
order = {"id": "o1", "customerId": "c1", "total": 42.5}
saved = orders.upsert_item(order) # write
show("write", saved.get_response_headers())
orders.read_item("o1", partition_key="c1") # read
show("read", orders.client_connection.last_response_headers)
pages = [] # the hook sees each page
rows = orders.query_items("SELECT * FROM c WHERE c.total > 10",
partition_key="c1", response_hook=lambda h, _: pages.append(h))
list(rows) # query
show("query", rows.get_response_headers())
print("query pages seen by the hook:", len(pages))
print("value on the emulator:", rows.get_response_headers()[HDR],
"(the emulator reports 1 for everything)")$ python charge.py
write x-ms-request-charge in headers: True
read x-ms-request-charge in headers: True
query x-ms-request-charge in headers: True
query pages seen by the hook: 1
value on the emulator: 1 (the emulator reports 1 for everything)The header is there for all three: in headers: True for the write, the read and the query. The hook saw 1 page. The value on the emulator is 1, as it is for everything, so it says nothing about cost. Real numbers come from an Azure account.
| Read it from | How |
|---|---|
| write, read | get_response_headers(), last_response_headers |
| query | get_response_headers(): latest page only |
| every page | response_hook |
| the portal | Data Explorer: Query Stats |
For queries, get_response_headers() returns the latest page only. So we pass a response_hook, which sees every page, and add the charges up. In the portal, Data Explorer shows the charge under Query Stats.
I log the charge of every hot query in a test against Azure, and fail the build when one jumps.
Question 4: The team must choose between database-level and container-level throughput. How do you decide?
With database-level throughput, the containers in a database share one pool of RU/s. With container-level, each container gets its own. Microsoft recommends container level for most workloads.
Let's create both. throughput.py makes shared_db with 1,000 RU/s shared by carts, wishlists and reviews. Then orders_db, where orders gets 4,000 RU/s of its own and events gets autoscale up to 10,000. We run python throughput.py.
from azure.cosmos import PartitionKey, ThroughputProperties
from common import client
pk = PartitionKey(path="/customerId")
# database level: 1000 RU/s shared by its containers
shared = client.create_database_if_not_exists(
"shared_db", offer_throughput=1000)
for name in ["carts", "wishlists", "reviews"]:
shared.create_container_if_not_exists(name, partition_key=pk)
# container level: each container gets its own RU/s
orders_db = client.create_database_if_not_exists("orders_db")
orders_db.create_container_if_not_exists(
"orders", partition_key=pk, offer_throughput=4000)
orders_db.create_container_if_not_exists(
"events", partition_key=pk, offer_throughput=ThroughputProperties(
auto_scale_max_throughput=10000))
for db in [shared, orders_db]:
print(db.id, sorted(c["id"] for c in db.list_containers()))$ python throughput.py
shared_db ['carts', 'reviews', 'wishlists']
orders_db ['events', 'orders']The emulator accepts all of it and lists the containers back: shared_db ['carts', 'reviews', 'wishlists'] and orders_db ['events', 'orders']. It doesn't enforce or report throughput, so the numbers live in the code.
| Database level (shared) | Container level (dedicated) | |
|---|---|---|
| RU/s | one pool for the database's containers | reserved for one container |
| Guarantee | none for a single container | predictable; recommended for most |
| Fits | many small, quiet containers (up to 25) | busy or critical containers |
| Change later | not in place: move the data | not in place: move the data |
Shared fits many small containers with low, uneven traffic, up to 25 per database. But no single container gets a guarantee:
- Shared - one busy container can starve the rest
- Dedicated - predictable for each container
We choose this when we create the database and the container. Switching later means moving the data to a new container.
Question 5: Traffic is quiet at night and busy during the day. How do autoscale and serverless change the bill?
With manual throughput, we pay for the RU/s we set, every hour. Sized for the lunch peak, it pays for that peak all night. Autoscale scales between 10 percent of a max we set and the max, and each hour is billed at the highest RU/s reached in that hour. With dynamic scaling, the default on newer accounts, that's per partition and region.
Let's apply the rule to one day. bill.py takes the highest RU/s in each of 24 hours, with a max of 10,000, and compares manual at the peak with autoscale. We run python bill.py.
TMAX = 10000 # autoscale max RU/s
peak = ([300] * 7 + [3000] * 2 + [8000] * 3 + [10000] * 2
+ [8000] * 4 + [2000] * 6) # highest RU/s in each hour
manual = TMAX * len(peak) # manual: set at the peak all day
auto = sum(max(TMAX // 10, p) for p in peak) # 10 percent floor
full = sum(p == TMAX for p in peak)
print("hours in the day:", len(peak))
print("manual 10000 RU/s:", manual, "RU/s-hours billed")
print("autoscale max 10000:", auto, "RU/s-hours billed")
print("hours at the max:", full, "of", len(peak))$ python bill.py
hours in the day: 24
manual 10000 RU/s: 240000 RU/s-hours billed
autoscale max 10000: 101000 RU/s-hours billed
hours at the max: 2 of 24Manual at the peak bills 240000 RU/s-hours, autoscale 101000, and the max was hit in 2 of 24 hours.
These are units, not money. With one write region, an autoscale RU/s costs more per hour than a manual one. Hence Microsoft's rule: if you use the full max in 66 percent of the hours in a month or fewer, autoscale can save costs.
| Manual | Autoscale | Serverless | |
|---|---|---|---|
| You set | RU/s, steps of 100 | a max, steps of 1000 | nothing |
| Billed on | RU/s set, every hour | highest RU/s each hour | RUs consumed + storage |
| Rate per RU/s | standard | higher with one write region | per RU consumed |
| Range | fixed | 10 to 100 percent of max | 5,000 RU/s per physical partition |
| Limits | at least 400 | max of at least 1000 | one region, no shared databases |
| Fits | steady traffic | busy days, quiet nights | dev, test, spiky low traffic |
We can switch modes any time in the portal or the CLI:
# Azure CLI: switch a container to autoscale (or back)
az cosmosdb sql container throughput migrate \
--account-name shop-cosmos --resource-group rg-shop \
--database-name orders_db --name orders \
--throughput-type autoscale
# the service picks the starting max: then set yours
az cosmosdb sql container throughput update \
--account-name shop-cosmos --resource-group rg-shop \
--database-name orders_db --name orders --max-throughput 10000Serverless bills only the request units consumed, plus storage. But it's single region, up to 5,000 RU/s per physical partition, with no predictable throughput.
Serverless for dev, test and spiky, low-traffic apps. Autoscale for busy days and quiet nights. Manual for steady traffic.
Question 6: A teammate asks why a write costs more than a point read. What drives the RU charge?
A point read fetches one item by id and partition key. A write stores the item and updates the index.
| Documented RU costs (Azure) | RU |
|---|---|
| point read, 1 KB item | 1 |
| insert, 1 KB item, no indexing | about 5.5 |
| replace the same item | 2 times the insert |
| strong or bounded staleness read | about 2 times |
| point read, 100 KB item | 10 |
So the drivers are:
- Item size - bytes stored and read
- Property count - more to index on write
- Indexing policy - exclude what you never filter
- Consistency - strong, bounded: about 2x reads
- Query shape - point read beats any query
Let's compare two documents. size.py stores a small mug and a big one, with a 100 KB description and 200 spec fields, and prints each one's property count and size. The products container's indexing policy skips the description path, because nobody searches it. We run python size.py.
import json
from azure.cosmos import PartitionKey
from common import client
db = client.create_database_if_not_exists("shop")
products = db.create_container_if_not_exists(
"products", partition_key=PartitionKey(path="/category"),
indexing_policy={"includedPaths": [{"path": "/*"}],
"excludedPaths": [{"path": "/description/*"}]})
def props(d): # count every leaf property
return sum(props(v) if isinstance(v, dict) else 1
for v in d.values())
small = {"id": "p1", "category": "mugs", "name": "Blue mug",
"price": 9.5}
big = dict(small, id="p2", description="x" * 100_000,
specs={f"spec{i}": i for i in range(200)})
for doc in [small, big]:
products.upsert_item(doc)
got = products.read_item(doc["id"], partition_key="mugs")
body = {k: v for k, v in got.items() if not k.startswith("_")}
size = len(json.dumps(body, separators=(",", ":"))) # as sent
print(doc["id"], "properties:", props(body), "bytes:", size)$ python size.py
p1 properties: 4 bytes: 59
p2 properties: 205 bytes: 102666The small mug is properties: 4 bytes: 59. The big one is properties: 205 bytes: 102666. On Azure, a point read of the big item costs about 10 RUs, and its writes cost more too. The emulator charges 1 for everything, so it can't show this.
Move big blobs to Blob Storage, and don't index what you never filter on.
Scenario 7: Cosmos DB costs doubled this month and finance wants answers. Where do you look and what do you change?
Start from what we pay for:
- RU/s - manual, or the autoscale max
- x hours - billed every hour
- x regions - RU/s in each region
- + storage - per GB
In Cost Management, Cost analysis filtered to the Azure Cosmos DB service shows where it grew. Then ask what changed:
- A new region - the same RU/s again, in that region
- A raised throughput - set for a load and never lowered
- A manual container sized for the peak - pays the peak all night
- An autoscale max set too high - and its 10 percent floor with it
Then the containers. audit.py lists each container's partition key, indexed and skipped paths, and time to live. We run python audit.py.
from common import client
for d in sorted(x["id"] for x in client.list_databases()):
db = client.get_database_client(d)
for c in sorted(x["id"] for x in db.list_containers()):
p = db.get_container_client(c).read()
idx = p["indexingPolicy"] # skip system paths
inc = [i["path"] for i in idx["includedPaths"]
if "_ts" not in i["path"]]
exc = [e["path"] for e in idx["excludedPaths"]
if "_etag" not in e["path"]]
print(f"{d}/{c}", "key", p["partitionKey"]["paths"],
"index", inc, "skip", exc, "ttl", p.get("defaultTtl"))$ python audit.py
orders_db/events key ['/customerId'] index ['/*'] skip [] ttl None
orders_db/orders key ['/customerId'] index ['/*'] skip [] ttl None
shared_db/carts key ['/customerId'] index ['/*'] skip [] ttl None
shared_db/reviews key ['/customerId'] index ['/*'] skip [] ttl None
shared_db/wishlists key ['/customerId'] index ['/*'] skip [] ttl None
shop/orders key ['/customerId'] index ['/*'] skip [] ttl None
shop/products key ['/category'] index ['/*'] skip ['/description/*'] ttl NoneSix of the seven containers have index ['/*'] and skip [], so they index every path. Only shop/products skips ['/description/*'], and every container has ttl None. On Azure, we add each container's RU/s or autoscale max to this list. The emulator doesn't report throughput.
Then the workload:
- Hot partition - Insights: normalized RU consumption by PartitionKeyRangeID
- Queries without the partition key - 2 to 3 RU per physical partition
- Strong or bounded staleness reads - about 2 times the RU
And the extras: 30 or 35 day continuous backup charges for backup storage, while 7 days doesn't. Customer-managed keys add RU overhead on reads, writes and queries, and diagnostic logs in Log Analytics are billed too.
Then we change it:
| Finding | Change |
|---|---|
| manual RU/s sized for a peak | right-size it, or switch to autoscale |
| every path indexed | index only what queries filter on |
| hot queries without the partition key | put the key in the filter |
| old data kept forever | a time to live |
| regions nobody reads from | remove them |
Put each change next to the bill when you go back to finance.
Key points to remember
- A request unit = CPU, IO and memory in one number: a 1 KB point read is 1 RU
- 429 = over the RU/s budget: the SDK retries up to 9 times or 30 s, honoring retry-after
- Read x-ms-request-charge from headers, a response_hook or get_response_headers()
- Dedicated throughput for most containers; shared for many small ones
- Autoscale bills the highest RU/s per hour; serverless bills RUs consumed
The full script
This is a Python script that writes every file and runs every command above in order against the Cosmos DB emulator: run pip install azure-cosmos first, and set COSMOS_ENDPOINT and COSMOS_KEY.
Show the full script that writes the files and runs every step
# ========================================================================
# Cosmos DB Interview Q&A #3 - Request units, throughput and cost
# TechBrothersIT. Names and sample data are invented for teaching.
# Every step below was run on the official Azure Cosmos DB Linux emulator (vNext, Docker image)
# with azure-cosmos 4.17.1; the outputs in the video and the blog post are the real outputs.
# To run it yourself:
# 1. docker run -p 8081:8081 -p 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-latest
# and wait until its log says "Now listening on: http://0.0.0.0:8081".
# 2. pip install azure-cosmos
# 3. Set COSMOS_ENDPOINT=http://localhost:8081 and COSMOS_KEY to the emulator key
# (C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==),
# then run python CosmosDB_Interview_QA_03_Code.py. The scripts create their own databases and containers.
# Run it in an empty folder and on a freshly started emulator: it creates its files (and any local data
# files) there, and a second run on old data gives different output.
# Steps that restart the emulator say so in a comment: stop and start it by hand at that point.
# ========================================================================
import os, subprocess, time
def write(path, text):
if text is None:
if os.path.exists(path): os.remove(path)
return
os.makedirs(os.path.dirname(path) or ".", exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
f.write(text.strip("\n") + "\n")
def run(cmd, expect_error=False, allow_error=False, env=None):
print("\n$ " + cmd, flush=True)
rc = subprocess.run(cmd, shell=True, env=dict(os.environ, **(env or {}))).returncode
if rc != 0 and not (expect_error or allow_error):
raise SystemExit("stopped: this command was expected to succeed")
# Step 0: the starting files
write('common.py', """\
import os
from azure.cosmos import CosmosClient
client = CosmosClient(os.environ["COSMOS_ENDPOINT"],
credential=os.environ["COSMOS_KEY"])
""")
# Step 1: Read the SDK retry settings for 429s from the client config
write('retry_config.py', """\
import os
from azure.cosmos import CosmosClient
URL, KEY = os.environ["COSMOS_ENDPOINT"], os.environ["COSMOS_KEY"]
clients = {
"default": CosmosClient(URL, credential=KEY),
"tuned": CosmosClient(URL, credential=KEY,
retry_total=5, retry_backoff_max=15),
}
for name, c in clients.items():
r = c.client_connection.connection_policy.RetryOptions
print(f"{name:8} max_retries={r.MaxRetryAttemptCount}",
f"max_wait_s={r.MaxWaitTimeInSeconds}",
f"fixed_interval_ms={r.FixedRetryIntervalInMilliseconds}")
""")
run('python retry_config.py')
# Step 2: Read the request charge header after a write, a read and a query
write('charge.py', """\
from azure.cosmos import PartitionKey
from common import client
db = client.create_database_if_not_exists("shop")
orders = db.create_container_if_not_exists(
"orders", partition_key=PartitionKey(path="/customerId"))
HDR = "x-ms-request-charge"
def show(op, headers):
print(f"{op:6} {HDR} in headers: {HDR in headers}")
order = {"id": "o1", "customerId": "c1", "total": 42.5}
saved = orders.upsert_item(order) # write
show("write", saved.get_response_headers())
orders.read_item("o1", partition_key="c1") # read
show("read", orders.client_connection.last_response_headers)
pages = [] # the hook sees each page
rows = orders.query_items("SELECT * FROM c WHERE c.total > 10",
partition_key="c1", response_hook=lambda h, _: pages.append(h))
list(rows) # query
show("query", rows.get_response_headers())
print("query pages seen by the hook:", len(pages))
print("value on the emulator:", rows.get_response_headers()[HDR],
"(the emulator reports 1 for everything)")
""")
run('python charge.py')
# Step 3: A shared-throughput database and containers with their own RU/s or autoscale
write('throughput.py', """\
from azure.cosmos import PartitionKey, ThroughputProperties
from common import client
pk = PartitionKey(path="/customerId")
# database level: 1000 RU/s shared by its containers
shared = client.create_database_if_not_exists(
"shared_db", offer_throughput=1000)
for name in ["carts", "wishlists", "reviews"]:
shared.create_container_if_not_exists(name, partition_key=pk)
# container level: each container gets its own RU/s
orders_db = client.create_database_if_not_exists("orders_db")
orders_db.create_container_if_not_exists(
"orders", partition_key=pk, offer_throughput=4000)
orders_db.create_container_if_not_exists(
"events", partition_key=pk, offer_throughput=ThroughputProperties(
auto_scale_max_throughput=10000))
for db in [shared, orders_db]:
print(db.id, sorted(c["id"] for c in db.list_containers()))
""")
run('python throughput.py')
# Step 4: Autoscale billing rule applied to one day of traffic
write('bill.py', """\
TMAX = 10000 # autoscale max RU/s
peak = ([300] * 7 + [3000] * 2 + [8000] * 3 + [10000] * 2
+ [8000] * 4 + [2000] * 6) # highest RU/s in each hour
manual = TMAX * len(peak) # manual: set at the peak all day
auto = sum(max(TMAX // 10, p) for p in peak) # 10 percent floor
full = sum(p == TMAX for p in peak)
print("hours in the day:", len(peak))
print("manual 10000 RU/s:", manual, "RU/s-hours billed")
print("autoscale max 10000:", auto, "RU/s-hours billed")
print("hours at the max:", full, "of", len(peak))
""")
run('python bill.py')
# Step 5: A small and a big product document: size and property count
write('size.py', """\
import json
from azure.cosmos import PartitionKey
from common import client
db = client.create_database_if_not_exists("shop")
products = db.create_container_if_not_exists(
"products", partition_key=PartitionKey(path="/category"),
indexing_policy={"includedPaths": [{"path": "/*"}],
"excludedPaths": [{"path": "/description/*"}]})
def props(d): # count every leaf property
return sum(props(v) if isinstance(v, dict) else 1
for v in d.values())
small = {"id": "p1", "category": "mugs", "name": "Blue mug",
"price": 9.5}
big = dict(small, id="p2", description="x" * 100_000,
specs={f"spec{i}": i for i in range(200)})
for doc in [small, big]:
products.upsert_item(doc)
got = products.read_item(doc["id"], partition_key="mugs")
body = {k: v for k, v in got.items() if not k.startswith("_")}
size = len(json.dumps(body, separators=(",", ":"))) # as sent
print(doc["id"], "properties:", props(body), "bytes:", size)
""")
run('python size.py')
# Step 6: Audit every container: partition key, indexed paths, skipped paths, TTL
write('audit.py', """\
from common import client
for d in sorted(x["id"] for x in client.list_databases()):
db = client.get_database_client(d)
for c in sorted(x["id"] for x in db.list_containers()):
p = db.get_container_client(c).read()
idx = p["indexingPolicy"] # skip system paths
inc = [i["path"] for i in idx["includedPaths"]
if "_ts" not in i["path"]]
exc = [e["path"] for e in idx["excludedPaths"]
if "_etag" not in e["path"]]
print(f"{d}/{c}", "key", p["partitionKey"]["paths"],
"index", inc, "skip", exc, "ttl", p.get("defaultTtl"))
""")
run('python audit.py')
Part 4: Data Modeling
The sample data on this page is invented for teaching. Every terminal output is the real output of the command above it, run on the official Azure Cosmos DB Linux emulator (vNext) with azure-cosmos 4.17.1. Features the emulator does not support are shown as code. Part of the Real Time Azure Cosmos DB Interview Questions and Answers series on TechBrothersIT. Features, limits and their status (GA or preview) are current as of October 2026; check the official Azure Cosmos DB documentation (learn.microsoft.com/azure/cosmos-db) for anything you quote in an interview.



No comments:
Post a Comment
Note: Only a member of this blog may post a comment.