What is Azure Table Storage?
Azure Table Storage is a NoSQL datastore that stores structured data as a collection of entities (rows) in tables. It is:
- Schema-less — Each entity can have different properties (columns)
- Massively scalable — Petabytes of data, millions of entities
- Very cheap — Much cheaper than Azure SQL Database for simple lookups
- Fast for key-based lookups — Extremely fast when you query by partition key + row key
- Not relational — No joins, no foreign keys, limited query capability
The Data Model
The hierarchy in Table Storage:
- Storage Account — Top-level container
- Table — A collection of entities (like a database table)
- Entity — A single record (like a database row), up to 1 MB
- Property — A name-value pair within an entity (like a column), up to 252 custom properties
System Properties
Every entity automatically has three system properties:
| Property | Description |
|---|---|
| PartitionKey | Groups related entities together for scalability |
| RowKey | Unique identifier within a partition |
| Timestamp | Last modified time — managed automatically by Azure |
Example Entity
{
"PartitionKey": "India",
"RowKey": "user-001",
"Name": "Priya Sharma",
"Email": "priya@example.com",
"Plan": "Premium",
"CreatedDate": "2026-01-15",
"Timestamp": "2026-05-07T10:30:00Z"
}
Partition Key and Row Key
The combination of PartitionKey + RowKey must be unique across the entire table. Together they form the primary key.
Partition Key
Determines which partition (storage node) an entity lives on. Entities with the same partition key are stored together and can be retrieved very efficiently. Good partition key design is crucial for performance:
- Good partition keys — CountryCode, UserId range, Date (year-month), TenantId
- Bad partition key — A single value for all entities (creates a hot partition — all traffic goes to one node)
- Bad partition key — Completely unique per entity (defeats the purpose of partitioning — poor scan performance)
Row Key
Uniquely identifies an entity within a partition. Combined with PartitionKey, it provides the fastest possible lookup — O(1) time complexity regardless of table size.
Querying with OData
Table Storage uses OData (Open Data Protocol) filter expressions for queries. Querying by PartitionKey + RowKey is fastest. Queries across all partitions (table scans) are slow and expensive for large tables.
| Query Type | Speed | Use When |
|---|---|---|
| PartitionKey + RowKey | ⚡ Fastest (point lookup) | You know exactly which entity you want |
| PartitionKey only | ✅ Fast (partition scan) | You want all entities in a partition |
| PartitionKey + row range | ✅ Good | Range queries within a partition |
| Table scan (no partition key) | 🐢 Slow | Avoid — scans all partitions |
# Query by PartitionKey + RowKey (fastest)
az storage entity show \
--table-name users \
--partition-key "India" \
--row-key "user-001" \
--account-name mystorageaccount2026 \
--auth-mode login
# Query all entities in a partition
az storage entity query \
--table-name users \
--filter "PartitionKey eq 'India'" \
--account-name mystorageaccount2026 \
--auth-mode login
# Query with multiple filters
az storage entity query \
--table-name users \
--filter "PartitionKey eq 'India' and Plan eq 'Premium'" \
--account-name mystorageaccount2026 \
--auth-mode login
Working With Tables via CLI
# Create a table
az storage table create \
--name users \
--account-name mystorageaccount2026 \
--auth-mode login
# Insert an entity
az storage entity insert \
--table-name users \
--entity PartitionKey=India RowKey=user-001 Name=PriyaSharma Email=priya@example.com Plan=Premium \
--account-name mystorageaccount2026 \
--auth-mode login
# Update an entity
az storage entity merge \
--table-name users \
--entity PartitionKey=India RowKey=user-001 Plan=Enterprise \
--account-name mystorageaccount2026 \
--auth-mode login
# Delete an entity
az storage entity delete \
--table-name users \
--partition-key India \
--row-key user-001 \
--account-name mystorageaccount2026 \
--auth-mode login
Table Storage vs Cosmos DB
Azure Cosmos DB offers a Table API that is compatible with Azure Table Storage — you can migrate with minimal code changes. Cosmos DB is significantly more powerful but also more expensive:
| Feature | Table Storage | Cosmos DB Table API |
|---|---|---|
| Global distribution | Single region (or paired) | Multi-region, globally distributed |
| Latency SLA | No latency SLA | <10ms read, <15ms write (99th percentile) |
| Secondary indexes | No | Yes — on any property |
| Throughput | Shared, no guarantee | Dedicated, provisioned RU/s |
| Cost | Very cheap | More expensive |
| Best for | Simple lookups, cost-sensitive | Global apps, latency-sensitive, complex queries |
When to Use Table Storage
| Good Fit | Poor Fit |
|---|---|
| User profile lookups by ID | Complex relational queries with joins |
| Application configuration/settings | Transactions across multiple entities |
| Session state storage | Ad-hoc queries on non-key properties |
| Device telemetry by device ID | Global low-latency requirements |
| Simple audit logs | Reporting and analytics workloads |