Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 4

Data Partitioning and Sharding for Stateful Services

Recommended resources

Welcome to the next lesson in our journey through distributed systems. In our previous session, we delved into consensus algorithms like Raft, which provide the machinery for a small group of servers to act as a single, strongly consistent, and fault-tolerant unit. This is fundamental for reliability. But what happens when the sheer volume of data or the intensity of user requests overwhelms the capacity of even the most powerful single server or a single Raft cluster?

This lesson tackles that exact problem: scaling beyond the limits of a single machine. We will move from the vertical scaling approach of "buy a bigger server" to the horizontal scaling strategy of "add more servers." This is a cornerstone of modern infrastructure, especially in AI systems that manage vast model metadata stores or billions of vector embeddings. We will explore the core techniques of data partitioning and sharding to distribute data and load across a fleet of machines. By the end of this lesson, you will be able to explain different sharding strategies and analyze their trade-offs for scaling stateful services.

The Limit of Scaling Up

As an application grows, its database is often the first component to feel the strain. The initial response, known as vertical scaling or "scaling up," is to upgrade the server to one with more CPU, more RAM, and faster storage. This is simple and effective, but only up to a point.

Eventually, you will hit a wall. There are hard physical and financial limits to how powerful a single machine can be. When your dataset size exceeds the storage of the largest available server, or the request throughput (e.g., writes per second) saturates its CPU and I/O capacity, vertical scaling is no longer an option.

This is the inflection point where horizontal scaling, or "scaling out," becomes necessary. The video below provides an excellent overview of this transition and sets the stage for why sharding is an essential tool in a system architect's toolkit.

Sharding in System Design Interviews w/ Meta Staff Engineer

This video from Hello Interview, featuring a staff engineer from Meta, clearly explains the motivation for sharding by walking through the limitations of vertical scaling.

Watch the initial segment that describes the journey from a single database to the point where vertical scaling is no longer sufficient, introducing sharding as the solution. Pay attention to the discussion of storage and throughput limits.


Partitioning vs. Sharding: Clarifying the Terms

The core idea of horizontal scaling is to split your data across multiple machines. This is where the terms "partitioning" and "sharding" come into play. They are often used interchangeably, but it's valuable to understand the nuance, as it clarifies the architecture.

  • Partitioning is the act of dividing a large dataset into smaller, more manageable, and independent subsets. Think of it as splitting a single large table into several smaller logical tables. These subsets are the partitions.
  • Sharding is the process of placing these partitions onto different database servers. Each server, which holds a subset of the total data, is called a shard.

So, you partition the data, and then you distribute those partitions across multiple shards.

The following video from Arpit Bhayani provides a crisp explanation of this distinction and presents a useful framework for thinking about the different ways these concepts can be combined.

Database Sharding and Partitioning

This video clearly differentiates between partitioning (a data-level concept) and sharding (a machine-level concept).

First, watch the brief segment that defines the terms sharding and partitioning. Then, focus on the excellent mental model presented in the section "A holistic view". This part illustrates the four possible scenarios: No Sharding / No Partitioning (a simple, single database) Partitioning / No Sharding (logical data splits on one server) Sharding / No Partitioning (data is replicated, not split, as in read replicas) Sharding and Partitioning (true horizontal scaling for writes and storage) This lesson focuses primarily on the fourth scenario.


Designing a Sharding Strategy

Now that we've established the "why" and "what," let's focus on the "how." A sharding strategy consists of two fundamental decisions:

  1. The Shard Key: Which piece of information will you use to decide which partition a piece of data belongs to?
  2. The Distribution Strategy: What is the algorithm for mapping a shard key to a specific shard?

1. Choosing a Shard Key

The shard key is the column or field in your data that you partition on. For example, in a user database, you might shard by user_id. All data related to a specific user (their profile, posts, etc.) would then be located in the same partition and, therefore, on the same shard.

A good shard key has three critical properties:

  • High Cardinality: The key should have many unique values. Sharding by a boolean flag like is_premium would be a disaster, as it would create only two partitions, severely limiting your ability to scale.
  • Even Distribution: The key should distribute data and, more importantly, load as evenly as possible across shards. Sharding a time-series database by timestamp can create a "hotspot," where the most recent partition receives all the write traffic.
  • Query Alignment: The key should align with your most common access patterns. If most of your queries are for a specific user's data, sharding by user_id is ideal because the query can be routed to a single shard instead of being broadcast to all of them.

2. Choosing a Distribution Strategy

Once you have a shard key, you need a rule to map it to a shard. Here are the most common strategies.

  • Range-Based Sharding: Data is partitioned based on ranges of the shard key (e.g., User IDs 1-1,000,000 on Shard 1, 1,000,001-2,000,000 on Shard 2, etc.). This is simple to understand but can easily lead to hotspots if the key is sequential (e.g., all new users go to the last shard).
  • Hash-Based Sharding: The shard key is fed into a hash function, and the output determines the shard. A common approach is shard_id = hash(shard_key) % num_shards. This typically results in a very even, random-like distribution of data, avoiding the hotspot problems of range-based sharding. Its main drawback is that adding or removing shards requires re-distributing almost all the data. We'll see in a future lesson how consistent hashing elegantly solves this rebalancing problem.
  • Directory-Based Sharding: A central lookup table (a directory) explicitly stores the mapping from each shard key value to its corresponding shard. This offers maximum flexibility—you can move a hot partition to a new shard just by updating the directory—but it introduces a single point of failure and adds an extra network hop to every request.

The same video from Hello Interview provides a clear walkthrough of these key choices and their trade-offs.

Sharding in System Design Interviews w/ Meta Staff Engineer

This part of the video breaks down the two core decisions in sharding: choosing the key and choosing the distribution strategy.

Watch the section on choosing a shard key, which covers the properties of good and bad keys with clear examples. Then, continue with the section on distribution strategies, which compares range-based, hash-based, and directory-based sharding.


Sharding in the Context of AI Systems

These general principles apply directly to the stateful services common in AI infrastructure. A model registry might shard its metadata by model_id, and a feature store could shard by entity_id. Your interest in vector databases makes them a perfect case study for seeing these strategies in action.

When sharding a vector index containing billions of items, the goal is to distribute the index across a cluster to overcome memory limits and parallelize search computation. Let's look at how the general strategies we've discussed map to this domain.

Sharding Strategies for Vector Indexes

This article from apxml.com provides a fantastic, AI-centric view of sharding. It discusses why sharding is critical for large-scale vector search and details three key strategies.

Please read the introduction and the sections on the three main strategies: Start with the introduction to understand the motivation for sharding vector indexes. Read about Random Sharding, which is equivalent to the hash-based strategy we just discussed. Note its major drawback: query broadcasting. Next, read about Metadata-Based Sharding. This is a powerful technique that avoids broadcasting when queries filter on the shard key. Finally, read about Vector-Based Sharding. This is a more complex, AI-native approach that tries to group semantically similar vectors on the same shard to optimize search.

As you can see, the choice of strategy involves significant trade-offs:

  • Random (Hash-based) Sharding is simple and gives good load balance, but it forces a costly "scatter-gather" operation where a query must be sent to every shard.
  • Metadata-based Sharding is extremely effective if your queries frequently filter by a specific attribute (like a customer ID or document category), as it prunes the search space to a single shard.
  • Vector-based Sharding attempts to optimize for pure similarity search by placing similar vectors together. This can reduce the number of shards that need to be queried, but it adds significant complexity in building and maintaining the clusters.

Putting It All Together: A Decision Matrix

The right strategy always depends on the specific scenario—the data characteristics, query patterns, and system requirements. Let's look at a decision matrix that maps common scenarios to optimal strategies for sharding and other related techniques.

This matrix illustrates how different system scenarios (like e-commerce, log analytics, image search, and personalization) map to different optimal strategies for sharding, partitioning, caching, and replication.

Take a moment to analyze the rows for Image Search and User Personalization, which are highly relevant to AI applications:

  • Image Search:

    • Sharding: Hash-Based. This suggests the primary goal is even load distribution for a large, static dataset where queries don't have a natural metadata filter.
    • Partitioning: K-Means. This corresponds to the vector-based (clustering) strategy. The system first partitions the vector space into similarity clusters and then distributes those partitions across shards. This is a hybrid approach to optimize pure similarity search.
  • User Personalization:

    • Sharding: Hash-Based on User ID. This is a classic choice for even load distribution.
    • Partitioning: Logical partitioning by user segment or behavior groups. This is a form of metadata-based partitioning. If a query is for a specific user, it can be routed directly to the correct shard.

This matrix highlights that there is no single "best" strategy. Effective system design involves analyzing the use case and selecting the appropriate combination of techniques.


Conclusion

In this lesson, we bridged the gap between a single, reliable service and a massively scalable one. You've seen that when vertical scaling reaches its limits, horizontal scaling through sharding becomes essential.

Here are the key takeaways:

  • Partitioning vs. Sharding: You partition your data into logical subsets and distribute those partitions across physical server shards.
  • Strategic Choices: A successful sharding strategy depends on choosing an appropriate shard key (high cardinality, even distribution, query-aligned) and a distribution strategy (hash-based, range-based, etc.).
  • Context is King: The optimal strategy is dictated by your application's access patterns. Random/hash-based sharding is a good default for load balancing, while metadata-based sharding is powerful for targeted queries. AI-specific techniques like vector-based clustering offer further optimization at the cost of complexity.
  • Trade-offs are Unavoidable: Sharding introduces operational complexity, and operations that span multiple shards (cross-shard queries) are expensive and should be minimized through careful shard key selection.

We have now distributed our data across many machines. But how do these machines coordinate? How does a client's request get routed to the right shard? How are results from multiple shards aggregated? This introduces the need for robust communication between system components. In our next lesson, we will explore the fundamental distributed communication patterns, such as RPCs and message queues, that serve as the connective tissue for sharded and other distributed architectures.