This chapter covers Azure Table Storage, a NoSQL key-value store that is part of Azure Storage. It is a core service for storing structured, non-relational data at massive scale. For the AZ-204 exam, Table Storage appears in approximately 5-10% of questions, often in the context of choosing the right data store for a given scenario, understanding its consistency model, and knowing its limits. You will need to understand how to design partition keys, query data, and handle scalability. This chapter provides a deep dive into the mechanics, configuration, and exam-relevant details.
Jump to a section
Imagine a massive filing cabinet with thousands of drawers. Each drawer represents a table, and inside each drawer are folders (entities) that can hold different types of forms (properties). The cabinet is organized by a key system: each folder has a unique combination of a drawer label (partition key) and a folder number (row key). When you need a specific folder, you go to the correct drawer and pull the folder by its number. If you need all folders in a drawer, you can quickly flip through them because they are physically grouped. The cabinet itself is infinitely expandable—you can add more drawers as needed without reorganizing existing ones. However, you cannot rename drawers or folders easily; you must create new ones and move the contents. Also, the cabinet does not enforce that all folders in the same drawer have the same set of forms—some may have extra fields or missing ones. To query across drawers, you must scan all drawers, which is slow. The cabinet's index is only on the drawer and folder labels; if you need to find folders by other attributes, you must create a separate cross-reference index (secondary index). This is exactly how Azure Table Storage works: a schemaless NoSQL key-value store with a composite key (partition key + row key), automatic scaling, and no support for cross-partition queries without full scans.
What is Azure Table Storage?
Azure Table Storage is a fully managed NoSQL key-value store that stores semi-structured data as entities. Each entity is a set of properties (name-value pairs) and is uniquely identified by a composite primary key consisting of a partition key and a row key. The service is schemaless, meaning entities in the same table can have different sets of properties. Table Storage is designed for storing large amounts of structured data that does not require complex joins, foreign keys, or stored procedures. It is ideal for web application user data, device telemetry, metadata, and other scenarios where low latency and high scalability are required.
How it works internally
Azure Table Storage is built on top of Azure Storage infrastructure. Data is stored in partitions, where each partition is a contiguous range of entities that share the same partition key. The partition key determines the physical location of the data. Within a partition, entities are sorted by row key. The service uses a hash of the partition key to distribute partitions across storage nodes. This means that entities with the same partition key are stored together, enabling efficient point queries and range queries within a partition.
When you insert an entity, the client SDK sends a REST API request to the Azure Storage front-end, which routes the request to the appropriate partition server based on the partition key hash. The server then stores the entity in a B-tree structure indexed by row key. Queries that specify both partition key and row key are the fastest (point queries). Queries that specify only partition key return all entities in that partition sorted by row key. Queries without partition key perform a full table scan across all partitions, which is slow and should be avoided.
Key components, values, defaults, and timers
Table: A named collection of entities. Tables are scoped to a storage account. Maximum table size is 500 TiB per storage account.
Entity: A single record, up to 1 MB in size. Each entity has a maximum of 252 properties (plus the three system properties: PartitionKey, RowKey, Timestamp).
PartitionKey: A string that determines the partition. Required. Maximum size 1 KB.
RowKey: A string that uniquely identifies an entity within a partition. Required. Maximum size 1 KB.
Timestamp: A system-generated DateTime property that indicates the last time the entity was modified. It is used for optimistic concurrency.
Properties: Name-value pairs. Property names are strings up to 128 characters. Property values can be of types: Edm.String, Edm.Binary, Edm.Boolean, Edm.DateTime, Edm.Double, Edm.Guid, Edm.Int32, Edm.Int64.
Maximum storage account capacity: 500 TiB per storage account.
Maximum table size: 500 TiB.
Maximum entity size: 1 MB.
Maximum number of properties per entity: 252.
Maximum table per storage account: Unlimited, but practical limits exist due to performance.
Request timeout: Default 30 seconds, configurable up to 2 minutes.
Consistency model: Strong consistency for entity operations within a partition. Cross-partition operations are eventually consistent.
Configuration and verification commands
To create a table using Azure CLI:
az storage table create --account-name <storage-account-name> --name <table-name> --auth-mode loginTo list tables:
az storage table list --account-name <storage-account-name> --auth-mode loginTo insert an entity using Azure CLI (requires connection string or SAS):
az storage entity insert --account-name <storage-account-name> --table-name <table-name> --entity PartitionKey=pk RowKey=rk Name=John --connection-string <connection-string>To query entities:
az storage entity query --account-name <storage-account-name> --table-name <table-name> --filter "PartitionKey eq 'pk'" --connection-string <connection-string>Using .NET SDK (Azure.Data.Tables package):
var serviceClient = new TableServiceClient(connectionString);
var tableClient = serviceClient.GetTableClient("mytable");
await tableClient.CreateIfNotExistsAsync();
var entity = new TableEntity("pk", "rk")
{
{ "Name", "John" },
{ "Age", 30 }
};
await tableClient.AddEntityAsync(entity);
var result = await tableClient.GetEntityAsync<TableEntity>("pk", "rk");How it interacts with related technologies
Azure Storage SDKs: Provide client libraries for .NET, Java, Python, Node.js, and others. These SDKs handle retry policies, connection management, and serialization.
Azure Functions: Can be triggered by Table Storage changes using the Table Storage binding. For example, a function can process new entities as they are inserted.
Azure Logic Apps: Connectors available for reading and writing to Table Storage.
Azure Data Factory: Can copy data to/from Table Storage from various sources.
Azure Search: Can index Table Storage data for full-text search.
Azure Cosmos DB: A more feature-rich alternative with Table API compatibility, offering global distribution, multi-master, and lower latency guarantees.
Performance considerations
Partition design: Choose partition keys that distribute workload evenly. Avoid hot partitions where a single partition receives high traffic. For example, use a hash of user ID rather than a sequential date.
Entity size: Keep entities small to reduce latency and cost. Each entity contributes to storage costs and request costs.
Batch operations: Up to 100 entities per batch, all must share the same partition key. Batching reduces request overhead.
Query optimization: Always include partition key in queries when possible. Use filters on row key for range scans within a partition. Avoid cross-partition queries.
Throughput limits: Target 2,000 entities per second per partition. Storage account limits: up to 20,000 IOPS (ingress + egress) for standard accounts. Use premium table storage for higher throughput.
Security
Authentication: Supports storage account key, shared access signature (SAS), and Azure AD (RBAC) via storage blob data contributor role (preview for tables).
Encryption: Data is encrypted at rest using Microsoft-managed keys or customer-managed keys. In-transit encryption via HTTPS.
Firewall and virtual networks: Can restrict access to specific IP addresses or virtual networks.
Limitations
No secondary indexes by default (can be implemented manually).
No foreign keys, joins, or stored procedures.
Maximum entity size 1 MB.
No support for transactions across partitions.
Property names are case-sensitive.
Table names must be alphanumeric, 3-63 characters, starting with a letter or number, no consecutive dashes.
Partition key and row key values are case-sensitive and must be strings (converted automatically if other types).
Use cases
Storing metadata for files in blob storage.
Storing user profiles for a web application.
Storing device telemetry data.
Storing log entries.
Storing configuration data.
When not to use
When you need complex queries with joins.
When you need global distribution with multi-master writes (use Cosmos DB instead).
When you need transactions across multiple partitions.
When data is highly relational.
Exam relevance
AZ-204 expects you to know how to choose between Table Storage, Cosmos DB, and SQL Database. Key differentiators: Table Storage is simpler, cheaper, and has lower latency for simple key-value lookups. Cosmos DB offers global distribution, multi-master, and multiple consistency levels. SQL Database is for relational data. Also know the limits: 1 MB entity, 252 properties, 500 TiB per table, 2,000 entities/sec per partition. Be familiar with the SDK operations and batch constraints.
Create a Storage Account
First, you need an Azure Storage account. This is the container that holds all your tables. When creating the account, you choose the performance tier (Standard or Premium) and the replication strategy (LRS, GRS, RA-GRS, etc.). For Table Storage, Standard accounts are sufficient for most workloads. Premium accounts provide higher throughput and lower latency but are more expensive. The storage account also provides the connection string or access keys that your application will use to authenticate. Note that Table Storage is enabled by default on all storage accounts.
Create a Table
Within the storage account, you create a table. A table is a logical container for entities. You can create a table using the Azure portal, Azure CLI, PowerShell, or SDK. The table name must be unique within the storage account and follow naming rules: 3-63 characters, alphanumeric, no consecutive dashes. Once created, the table exists and can store entities. There is no schema definition at this point.
Design Partition and Row Keys
Before inserting data, you must decide on the partition key and row key design. The partition key determines how data is distributed across servers. A good partition key ensures even load distribution and efficient queries. For example, if you are storing user data, using UserID as partition key might be good if users are many and evenly accessed. Avoid using a single partition key for all entities (e.g., 'all') as that creates a hot partition and limits scalability. The row key uniquely identifies an entity within a partition. It can be used for range queries. For time-series data, using a timestamp as row key allows querying by time range.
Insert Entities
Insert entities using the SDK or REST API. Each entity must have PartitionKey and RowKey properties. You can add additional properties as needed. The SDK serializes the entity to JSON and sends a POST request to the table endpoint. The service validates that the entity size is within 1 MB and the number of properties does not exceed 252. If successful, the entity is stored and a timestamp is assigned. You can insert up to 100 entities in a single batch operation, but all must share the same partition key. Batch operations are atomic within the partition.
Query Entities
To retrieve data, you issue queries. The most efficient query specifies both partition key and row key (point query). You can also query by partition key only, which returns all entities in that partition sorted by row key. Queries without partition key perform a full table scan and are slow. You can filter on property values using OData syntax. Filters on partition key and row key are indexed; filters on other properties are not indexed unless you create a secondary index manually (e.g., by storing a copy in another table). The query returns up to 1,000 entities by default; you can use continuation tokens to paginate.
Update and Delete Entities
Update operations can be either replace (put) or merge (patch). Replace overwrites the entire entity; merge updates only specified properties. Both require the PartitionKey and RowKey. You can use ETags for optimistic concurrency: if the ETag has changed since you last read, the update fails. Delete operations remove an entity by its partition and row key. You can also delete a table, which removes all entities in it. Batch operations can include updates and deletes as long as they are within the same partition.
Enterprise Scenario 1: User Profile Store for a Social Media App
A social media company with 50 million users needs to store user profiles (username, email, display name, avatar URL, preferences). They chose Azure Table Storage because it is cost-effective and can handle the scale. They designed the partition key as a hash of the user ID to distribute load evenly across partitions. The row key is the user ID itself (since it's unique). They use the .NET SDK to read and write profiles on every login. The system handles 10,000 requests per second with average latency under 10 ms. A common misconfiguration is using the user ID directly as partition key without hashing, leading to uneven distribution if user IDs are sequential. They also implemented a secondary index for email lookup by storing a separate table with email as partition key and user ID as row key. When a user changes their email, they update both tables in a batch (though batch only works within same partition, so they must handle consistency manually). Performance issues arise when a single partition becomes hot due to a celebrity user; they mitigated by adding a sub-partition (e.g., appending a random digit to the hash).
Enterprise Scenario 2: IoT Device Telemetry
A manufacturing company collects telemetry from 100,000 sensors every minute. They store data in Azure Table Storage with partition key as DeviceID and row key as inverted timestamp (DateTime.MaxValue.Ticks - timestamp) to ensure most recent entries appear first in queries. They use batch inserts to reduce costs. The system ingests 1.7 million entities per day. They query by device and time range to generate reports. A common issue is that the partition key is too granular (each device has its own partition), leading to many small partitions and slower cross-device queries. They solved this by using a coarser partition key, such as facility ID, but then faced hot partitions for busy facilities. They eventually moved to Cosmos DB for better global distribution and multi-region writes. For the exam, remember that Table Storage is suitable for IoT telemetry if queries are primarily per device.
Enterprise Scenario 3: Metadata Store for Blob Storage
A media company stores millions of video files in Azure Blob Storage. They use Table Storage to store metadata (filename, upload date, duration, tags, status). The partition key is the first two characters of the blob name (a simple hash) to distribute load. The row key is the full blob name. They use Azure Functions triggered by blob uploads to insert metadata into the table. This allows fast lookups by blob name and range queries by date. A misconfiguration is not using a partition key that distributes load, causing throttling. They also learned that the 1 MB entity limit is not an issue for metadata, but they had to be careful not to store large tags. They use continuation tokens for pagination when listing all blobs. This pattern is common and often tested on the exam as a valid use case for Table Storage.
Exactly what AZ-204 tests on this topic
AZ-204 objective 2.2: 'Implement Azure Table Storage'. The exam tests your ability to:
Choose between Table Storage, Cosmos DB, and Azure SQL Database for a given scenario.
Design partition keys and row keys for optimal performance.
Understand the consistency model (strong within partition, eventual across partitions).
Know the limits: entity size 1 MB, 252 properties, 500 TiB per table, 2,000 entities/sec per partition.
Use SDK operations: insert, query, update, delete, batch.
Understand the use of continuation tokens.
Know how to authenticate using connection string, SAS, or Azure AD.
Recognize when to use premium table storage (low latency, high throughput).
Common wrong answers and why candidates choose them
Choosing Cosmos DB when Table Storage is sufficient: Candidates often pick Cosmos DB because it sounds more advanced. However, if the scenario only needs simple key-value lookups with no global distribution or multi-master writes, Table Storage is cheaper and simpler. The exam expects you to consider cost and complexity.
Using a single partition key for all entities: Some candidates think that putting all data in one partition makes queries simple. This creates a hot partition and limits throughput. The correct approach is to distribute data across partitions.
Thinking Table Storage supports secondary indexes: It does not natively. Candidates might assume it does because SQL databases have indexes. The exam may present a scenario requiring indexing on non-key properties; the correct answer is to implement a manual index or use Cosmos DB.
Assuming strong consistency across partitions: Table Storage provides strong consistency only within a partition. Cross-partition operations are eventually consistent. Candidates may forget this and choose Table Storage for a scenario requiring global strong consistency.
Specific numbers and values that appear verbatim on the exam
Entity size: 1 MB
Maximum properties per entity: 252
Maximum table size: 500 TiB
Maximum request timeout: 30 seconds (default)
Batch size: 100 entities, same partition key
Throughput: 2,000 entities per second per partition
Storage account throughput: up to 20,000 IOPS for standard
Edge cases and exceptions the exam loves to test
Empty string as partition key: Allowed, but not recommended. Entities with empty string partition key all go to the same partition.
Special characters in keys: Partition key and row key must be strings. The SDK handles URL encoding.
Timestamp property: It is system-managed and cannot be updated directly. Used for optimistic concurrency.
Batch operations: Must be within the same partition. The exam may present a scenario where you need to update two entities in different partitions; the correct answer is to use two separate requests, not a batch.
How to eliminate wrong answers using the underlying mechanism
If the scenario requires transactions across multiple partitions, eliminate Table Storage because it does not support cross-partition transactions.
If the scenario requires secondary indexes, eliminate Table Storage unless the answer includes manually maintaining a separate table.
If the scenario requires storing entities larger than 1 MB, eliminate Table Storage.
If the scenario requires global distribution with multi-region writes, eliminate Table Storage and choose Cosmos DB.
If the scenario requires low latency (<10 ms) and high throughput (>20,000 entities/sec), consider premium table storage or Cosmos DB.
Azure Table Storage is a NoSQL key-value store with a composite primary key (PartitionKey + RowKey).
Maximum entity size is 1 MB with up to 252 properties.
Strong consistency is only within a partition; cross-partition operations are eventually consistent.
Always include partition key in queries for best performance; avoid full table scans.
Batch operations are limited to 100 entities and must share the same partition key.
Table Storage does not support secondary indexes, foreign keys, or transactions across partitions.
For global distribution or multi-master writes, use Cosmos DB Table API instead.
These come up on the exam all the time. Here's how to tell them apart.
Azure Table Storage
Cost-effective for simple key-value workloads
No global distribution by default (requires RA-GRS for read access in secondary region)
Strong consistency only within a partition
Throughput limited to ~2,000 entities/sec per partition (20,000 IOPS per account)
No secondary indexes, no multi-master writes
Azure Cosmos DB Table API
Higher cost but lower latency and higher throughput (millions of RU/s)
Global distribution with multi-master writes
Multiple consistency levels: strong, bounded staleness, session, consistent prefix, eventual
Automatic indexing of all properties
Supports secondary indexes, multi-master, and SLA-backed 99.999% availability
Mistake
Azure Table Storage is a relational database.
Correct
Table Storage is a NoSQL key-value store. It does not support foreign keys, joins, or stored procedures. It is schemaless, meaning entities can have different properties.
Mistake
You can have up to 1,000 properties per entity.
Correct
The maximum number of properties per entity is 252, including the three system properties (PartitionKey, RowKey, Timestamp).
Mistake
Table Storage supports secondary indexes by default.
Correct
Table Storage does not have built-in secondary indexes. To query on non-key properties efficiently, you must create a separate table or use a different data store like Cosmos DB.
Mistake
Table Storage provides strong consistency across all partitions.
Correct
Strong consistency is guaranteed only within a single partition. Cross-partition queries are eventually consistent. For strong consistency across partitions, use Cosmos DB with strong consistency level.
Mistake
You can store entities up to 2 MB in size.
Correct
The maximum entity size is 1 MB, including all property values. Any entity larger than 1 MB will be rejected.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
Azure Table Storage is a simpler, cheaper service with lower throughput and no global distribution. Cosmos DB Table API offers global distribution, multi-master writes, multiple consistency levels, automatic indexing, and higher throughput (millions of RU/s) but at a higher cost. Choose Table Storage for simple, cost-sensitive workloads with regional data. Choose Cosmos DB when you need global scale, low latency, or strong consistency across regions.
Yes, but it performs a full table scan across all partitions, which is very slow and inefficient. Always include the partition key in your queries to limit the scan to a single partition. If you must query without partition key, consider using Cosmos DB Table API which indexes all properties.
Table Storage does not natively support secondary indexes. To implement one manually, create a separate table where the desired indexed property becomes the partition key or row key. For example, to index by email, create a table with PartitionKey = email and RowKey = user ID. When you insert a user entity, also insert a corresponding entity in the index table (in separate requests, as batch requires same partition). This adds complexity and eventual consistency between tables.
There is no limit on the number of entities per table, but the total table size cannot exceed 500 TiB per storage account. With a maximum entity size of 1 MB, you can store up to approximately 500 million entities if each is 1 MB, but in practice entities are smaller, so you can store billions.
Table Storage uses optimistic concurrency control via ETags. When you read an entity, you get an ETag. When you update or delete, you must provide the ETag. If the entity was modified by another client, the ETag will not match and the operation fails with a 412 Precondition Failed error. You can also force an update without ETag by using a '*' value, which overwrites regardless.
Yes, Azure AD authentication is supported for Table Storage (in preview). You can assign RBAC roles such as 'Storage Table Data Contributor' to users or managed identities. This allows you to avoid storing connection strings or access keys. However, not all SDKs fully support it yet; check documentation.
Standard Table Storage is backed by HDDs and offers lower cost with throughput up to 20,000 IOPS per account. Premium Table Storage is backed by SSDs and provides higher throughput (up to 100,000 IOPS) and lower latency (single-digit milliseconds) but at higher cost. Premium is recommended for latency-sensitive applications.
You've just covered Azure Table Storage — now see how well it sticks with free AZ-204 practice questions. Full explanations included, no account needed.
Done with this chapter?