Optimal PartitionKey & RowKey Design for Blog Posts

Following on from a previous article looking into what is good practice for defining PartitionKey and RowKey for Azure Table storage, here we take a real life scenario and look at some of the possible values we could use for when storing a blog post.

🎯 Your main query patterns will likely be:

  • Get a single post by slug or ID
  • List posts by publish date
  • List posts by category or tag
  • List posts by author
  • Show the latest N posts

Azure Tables don’t support secondary indexes, so you design your keys around these patterns.


✔️ Recommended Primary Table: Posts

PartitionKey: yyyy-MM (publish month)

RowKey: slug or inverted timestamp

This gives you:

  • Fast “latest posts” queries
  • Natural grouping by month
  • Even distribution (no hotspots)
  • Easy retrieval of a single post

Example

PartitionKey RowKey Title
2025-02 my-first-post My First Post
2025-02 MaxTicks-638742... Another Post
2025-03 building-a-cms Building a CMS

Why this works

  • Blog posts are naturally time‑series data.
  • Monthly partitions keep partitions from getting too large.
  • You can fetch the latest posts by querying the most recent partitions.

✔️ Alternative RowKey Options

Option A: Slug (human‑friendly)

  • Easy to retrieve a post directly
  • Great for SEO‑style URLs
  • Good if slugs are unique

Option B: Inverted timestamp (machine‑friendly)

  • Perfect for “latest first” queries
  • RowKey sorts newest → oldest
  • Format:
    RowKey = (DateTime.MaxValue - PublishDate).Ticks.ToString("d19")

✔️ Handling Categories, Tags, and Authors

Azure Tables don’t support secondary indexes, so you create additional tables for fast lookups.

Table: PostsByCategory

  • PartitionKey: category
  • RowKey: yyyy-MM-dd-HH-mm-ss + slug
  • Value: pointer to the main post (PartitionKey + RowKey)

Table: PostsByTag

Same pattern as categories.

Table: PostsByAuthor

Same pattern again.

These tables act like manual indexes—super cheap, super fast.


✔️ Summary of the Best Practice

Table PartitionKey RowKey Purpose
Posts yyyy-MM slug or inverted timestamp Main storage
PostsByCategory category timestamp+slug Fast category queries
PostsByTag tag timestamp+slug Fast tag queries
PostsByAuthor authorId timestamp+slug Fast author queries

This structure scales beautifully and keeps queries predictable and cheap.