Develop for Azure storage
Storage decisions
Blob storage holds unstructured data. Understand tiers (Hot, Cool, Cold, Archive): Archive is offline, so reads fail until rehydration completes (hours). Lifecycle rules move blobs automatically. Concurrency uses ETags with If-Match, returning 412 on conflict; leases give exclusive write locks. Authorization options are account keys, SAS (account, service, or user delegation SAS signed by Entra credentials - the safest), and RBAC.
Cosmos DB: choose a partition key with high cardinality and even read/write spread; the key is immutable after creation. Throughput is RU/s, provisioned (manual or autoscale) or serverless. Five consistency levels run from strong to eventual; session is the default and is per-client. Stored procedures and triggers are scoped to a single partition key. Change feed lets you react to inserts and updates. SDK: CosmosClient → GetContainer → CreateItemAsync → FeedIterator.
Queues: 64 KB message limit, visibility timeout hides a message while processing, dequeue count routes poison messages to the poison queue. Delivery is at-least-once, so make processing idempotent. Table storage: PartitionKey + RowKey is the unique index; queries are cheap only on those keys.
Traps
Reading from Archive tier; assuming strong consistency is default; a stored procedure spanning partitions; expecting exactly-once queue delivery; SAS without a stored access policy (cannot be revoked early).
Worked example
Two clients read the same blob and both write. Read the blob with its ETag, write with If-Match: <etag>; on 412, re-read and retry. Last-write-wins with account keys loses data.
Rule of thumb
The partition key is what you query by most often, and it should have many distinct values.