INTERVIEW_QUESTIONS
Database Sharding Interview Questions for Senior Engineers (2026)
15 advanced database sharding interview questions with detailed answer frameworks covering horizontal partitioning, shard key selection, rebalancing strategies, and production patterns used at Google, Amazon, and other top companies.
Why Database Sharding Dominates Senior Engineering Interviews
Database sharding is one of the most frequently tested topics in senior and staff-level engineering interviews because it sits at the intersection of data modeling, distributed systems, and operational maturity. When an interviewer asks you to shard a database, they are not simply asking you to split data across machines. They are probing whether you understand the cascading consequences of that decision on query patterns, consistency guarantees, operational complexity, and application architecture.
At companies like Google and Amazon, sharding decisions made early in a system's life can constrain its evolution for years. Choosing the wrong shard key can create hotspots that bring down production. Failing to plan for cross-shard queries can cripple features that product teams depend on. Senior engineers are expected to anticipate these problems before they manifest, and interviewers use sharding questions to assess that foresight.
The questions in this guide go beyond textbook definitions. Each one is framed around the real intent behind the interviewer's question, followed by a structured answer framework that demonstrates both depth and practical experience. Whether you are preparing for a system design round that involves designing a service like Amazon's e-commerce platform or a deep-dive architecture discussion on how database sharding works in production, these questions will sharpen your ability to reason about sharding trade-offs under pressure. For a broader preparation strategy, see our system design interview guide and explore the learning paths tailored to senior engineers.
1. What is database sharding and why would you choose it over vertical scaling?
What the interviewer is really asking: Do you understand when sharding is genuinely necessary versus when simpler scaling approaches suffice? Can you articulate the cost of introducing sharding?
Answer framework:
Database sharding is a horizontal partitioning strategy where a single logical database is split into multiple smaller databases called shards, each residing on a separate server. Every shard holds a subset of the total data and can handle read and write operations independently. The fundamental motivation is to overcome the limitations of vertical scaling: a single machine, no matter how powerful, has finite CPU, memory, disk I/O, and network bandwidth. When a database reaches hundreds of millions of rows or thousands of transactions per second, vertical scaling becomes prohibitively expensive or physically impossible.
However, sharding is not a free lunch. It introduces significant complexity across multiple dimensions. Application logic must be aware of the sharding scheme to route queries to the correct shard. Cross-shard joins become expensive or impossible, requiring denormalization or application-level joins. Transactions that span multiple shards require distributed transaction protocols like two-phase commit, which are slower and more failure-prone. Schema changes must be coordinated across all shards. Operational tasks like backups, monitoring, and failover multiply in complexity.
Before choosing sharding, exhaust simpler approaches first: read replicas for read-heavy workloads, caching strategies for frequently accessed data, query optimization and proper indexing, connection pooling, and vertical scaling to larger instances. Only when these approaches are insufficient should you introduce sharding. In practice, many systems operate successfully without sharding until they reach significant scale. A well-optimized PostgreSQL or MySQL instance can handle millions of rows and thousands of queries per second.
The decision to shard should be driven by specific bottlenecks: write throughput exceeding what a single node can handle, dataset size exceeding available memory causing excessive disk I/O, or regulatory requirements mandating data residency in specific geographic regions.
Follow-up questions:
- At what data volume or query volume would you start considering sharding?
- How would you evaluate whether read replicas are sufficient before resorting to sharding?
- What are the operational costs of running a sharded database in production?
2. How do you choose a shard key, and what makes a shard key selection good or bad?
What the interviewer is really asking: Can you think systematically about data distribution, query patterns, and long-term growth when making a foundational architectural decision?
Answer framework:
The shard key is the single most consequential decision in a sharding strategy because it determines how data is distributed across shards and which queries can be efficiently served. A good shard key satisfies four properties simultaneously.
First, high cardinality: the shard key should have enough distinct values to distribute data evenly across all current and future shards. A boolean field is a terrible shard key because it only has two values. A user ID with millions of distinct values is much better. Second, even distribution: the values of the shard key should produce a roughly uniform distribution of data and load across shards. If 80 percent of queries target shard keys in a narrow range, that shard becomes a hotspot. Third, query isolation: the most common and most latency-sensitive queries should be satisfiable by a single shard. If your application primarily queries by user ID, sharding by user ID ensures that each user's data lives on one shard. Fourth, growth stability: the shard key should remain effective as data grows. Sharding by date means that only the current shard receives writes, creating a write hotspot.
Consider an e-commerce platform like Amazon. If you shard by customer_id, all of a customer's orders, addresses, and preferences live on one shard, enabling efficient lookups. But a query like "find all orders for product X" now requires a scatter-gather across all shards. If you shard by product_id instead, product queries are efficient but customer profile lookups scatter. The right choice depends on which access pattern dominates.
Compound shard keys can address multiple requirements. For a multi-tenant SaaS application, a shard key of (tenant_id, entity_id) keeps all tenant data together while distributing across tenants. For time-series data, a compound key of (sensor_id, time_bucket) distributes writes across sensors while keeping temporal data for each sensor co-located.
Avoid these common mistakes: using auto-incrementing IDs that create hotspots on the latest shard, using low-cardinality fields, choosing a key that does not align with query patterns, and selecting a key that cannot be changed later without a full data migration.
Follow-up questions:
- How would you handle a scenario where no single field satisfies all shard key requirements?
- What would you do if your shard key creates a hotspot in production?
- How does shard key selection differ between relational and NoSQL databases?
3. Explain the difference between hash-based sharding and range-based sharding. When would you choose each?
What the interviewer is really asking: Do you understand the trade-offs between data distribution uniformity and the ability to perform range queries efficiently?
Answer framework:
Hash-based sharding applies a hash function to the shard key and uses the hash value to determine the target shard, typically via modulo or consistent hashing. For example, shard_number = hash(user_id) mod N. This produces a near-uniform distribution regardless of the key distribution. The primary advantage is even data distribution with no hotspots. The primary disadvantage is that range queries become scatter-gather operations because adjacent key values map to different shards. Hash-based sharding is ideal when your primary access pattern is point lookups by the shard key.
Range-based sharding assigns contiguous ranges of the shard key to each shard. For example, shard 1 holds user IDs 1 to 1,000,000, shard 2 holds 1,000,001 to 2,000,000, and so on. The primary advantage is that range queries on the shard key can be directed to a small number of shards. The primary disadvantage is potential for uneven distribution and hotspots. If new users get sequentially increasing IDs, all writes hit the last shard.
The choice depends on your workload pattern. For a social media application where you primarily look up user profiles and activity by user ID, hash-based sharding provides even distribution and efficient lookups. For a time-series analytics platform where queries commonly request data for a date range, range-based sharding by time allows those queries to target a small number of shards.
Directory-based sharding uses a lookup table that maps each shard key value to a specific shard. This provides maximum flexibility since you can move individual keys between shards, but the directory becomes a single point of failure and a potential bottleneck.
In practice, many production systems use a hybrid approach. For example, MongoDB uses range-based sharding by default but supports hash-based sharding. CockroachDB uses range-based sharding with automatic range splitting. Google's Spanner uses a hierarchical approach where tables are interleaved for locality.
Follow-up questions:
- How does consistent hashing improve upon simple modulo-based hash sharding?
- What happens with range-based sharding when one range grows much faster than others?
- Can you combine hash-based and range-based sharding in the same system?
4. How does consistent hashing work and why is it important for database sharding?
What the interviewer is really asking: Can you explain a fundamental distributed systems primitive in depth, including virtual nodes and the practical impact on shard rebalancing?
Answer framework:
Consistent hashing solves the critical problem of shard rebalancing when nodes are added or removed. With simple modulo hashing (hash(key) mod N), changing N remaps nearly every key to a different shard, requiring a massive data migration. Consistent hashing limits the remapping to approximately K/N keys on average, where K is the total number of keys and N is the number of nodes.
The mechanism works by placing both nodes and keys on a virtual ring using the same hash function. Each key is assigned to the first node encountered when moving clockwise around the ring from the key's position. When a new node joins, it takes responsibility for a portion of its clockwise neighbor's key range. When a node leaves, its keys are reassigned to its clockwise neighbor. In both cases, only the keys in the affected range move.
The naive implementation has a problem: with few physical nodes, the distribution is uneven because nodes may cluster on one part of the ring. Virtual nodes solve this by mapping each physical node to many positions on the ring, typically 100 to 200 per physical node. This produces a statistically uniform distribution. When a physical node is added, its virtual nodes are spread across the ring, and it absorbs a small fraction of keys from many other nodes rather than a large fraction from one.
In practice, consistent hashing is the foundation of many distributed databases. Amazon DynamoDB uses consistent hashing for partition assignment. Apache Cassandra uses a token ring based on consistent hashing. Redis Cluster uses hash slots, which is conceptually similar.
When implementing consistent hashing, consider these details: the choice of hash function affects distribution uniformity. MurmurHash3 and xxHash are popular choices for their speed and distribution quality. The number of virtual nodes is a tuning parameter that balances distribution uniformity against memory overhead for the ring metadata. Weighted consistent hashing allows heterogeneous nodes where nodes with more capacity are assigned more virtual nodes.
Follow-up questions:
- How would you handle a scenario where one physical node has twice the capacity of others?
- What is the impact of consistent hashing on data locality and cache efficiency?
- How do you implement consistent hashing in a system that also needs range queries?
5. How would you handle cross-shard queries and transactions?
What the interviewer is really asking: Do you understand the fundamental tension between data distribution and query flexibility, and can you propose practical solutions that balance consistency, performance, and complexity?
Answer framework:
Cross-shard operations are the most significant cost of sharding. A query that touches a single shard completes in milliseconds with simple routing. A query that must touch all shards requires a scatter-gather pattern: the query is broadcast to every shard, each shard executes its portion, and results are aggregated at a coordinator node. This is orders of magnitude slower and introduces failure modes where a single slow shard delays the entire query.
For cross-shard queries, several strategies exist depending on the use case. First, denormalization: duplicate data across shards to avoid joins. If you frequently need user data alongside order data and they live on different shards, store a copy of the relevant user fields in the order table. This trades storage for query performance. Second, application-level joins: fetch data from multiple shards in parallel and join in the application layer. This gives you control over timeout and retry logic. Third, materialized views: pre-compute and store the results of common cross-shard queries in a separate read-optimized store. Fourth, CQRS (Command Query Responsibility Segregation): write to sharded stores for transactional integrity but replicate to an aggregated read store for analytics queries.
For cross-shard transactions, the standard approach is two-phase commit (2PC): a coordinator asks all participating shards to prepare (acquire locks and verify constraints), then sends a commit or abort to all. 2PC guarantees atomicity but is slow (two network round trips), blocking (participants hold locks during the protocol), and vulnerable to coordinator failure. In practice, many systems avoid 2PC entirely by designing the data model so that transactions stay within a single shard.
Alternatives to 2PC include the saga pattern where a sequence of local transactions on each shard is coordinated, with compensating transactions for rollback. This provides eventual consistency rather than strong consistency. Another approach is Google Spanner's TrueTime-based protocol, which achieves externally consistent distributed transactions using synchronized atomic clocks, but this requires specialized hardware infrastructure. Understanding the CAP theorem trade-offs is essential when reasoning about these approaches.
Follow-up questions:
- How do you handle a cross-shard query that must complete within 100ms?
- What monitoring would you put in place to detect cross-shard query performance degradation?
- When would you accept eventual consistency for cross-shard operations versus requiring strong consistency?
6. What is a hotspot in a sharded database and how do you detect and mitigate it?
What the interviewer is really asking: Can you identify operational problems that emerge in sharded systems and apply systematic approaches to diagnose and resolve them without downtime?
Answer framework:
A hotspot occurs when one shard receives a disproportionate share of traffic or stores a disproportionate amount of data compared to other shards. Hotspots negate the primary benefit of sharding by concentrating load on a single node while other nodes sit idle. They manifest in three forms: write hotspots (one shard receives most writes), read hotspots (one shard serves most reads), and storage hotspots (one shard holds significantly more data).
Common causes include a shard key with skewed distribution, celebrity accounts in social media where a single user generates massive traffic, temporal patterns where all current writes go to one shard, and organic data growth that concentrates in one key range.
Detection requires comprehensive monitoring: track per-shard metrics including query rate, latency percentiles (p50, p95, p99), CPU utilization, disk I/O, and storage size. Set alerts when any shard deviates significantly from the median. Monitor the standard deviation of query rates across shards. Use slow query logs to identify specific queries or keys causing hotspots.
Mitigation strategies depend on the hotspot type. For key-based hotspots (celebrity problem), add a random suffix to the shard key for hot keys, distributing their data across multiple shards. This is called key salting. Reads for hot keys now scatter across shards, but that trade-off is acceptable because the alternative is a single overloaded shard. For range-based hotspots, split the hot shard into two smaller shards by dividing its key range. Systems like HBase and CockroachDB do this automatically. For read hotspots, add read replicas specifically for the hot shard. Use a caching layer in front of the hot shard to absorb repeated reads.
Prevention is better than mitigation. During shard key selection, analyze the distribution of candidate keys against production data. Load test with realistic traffic patterns before launching. Build automated shard-splitting capabilities so that hotspots can be resolved without manual intervention.
Follow-up questions:
- How would you handle a flash sale event that you know will create a temporary hotspot?
- What is the operational procedure for splitting a hot shard in a live production system?
- How do you distinguish between a hotspot caused by key distribution versus a hotspot caused by a specific expensive query?
7. Describe the process of resharding or rebalancing a sharded database.
What the interviewer is really asking: Have you dealt with the operational complexity of changing a sharding scheme in a live production system? Do you understand the risks and can you plan a safe migration?
Answer framework:
Resharding is necessary when the current shard count is insufficient for the data volume or traffic, when hotspots require redistributing data, or when the shard key itself needs to change. It is one of the most complex and risky operations in database management.
The safest approach is online resharding, which maintains full service availability throughout the process. The general strategy involves five phases. Phase one, preparation: provision new shards, set up replication from old shards, and deploy the new shard routing logic behind a feature flag. Phase two, dual-write: the application writes to both the old and new shard configurations. Reads still go to the old shards. This ensures no writes are lost during migration. Phase three, backfill: copy historical data from old shards to new shards. This is the longest phase and must handle the fact that data is actively being modified. Use a consistent snapshot plus change data capture to replay writes that occurred during the copy. Phase four, verification: compare data between old and new shards to ensure consistency. Run checksums on random samples. Verify row counts. Phase five, cutover: switch reads to the new shards, verify correctness, then stop dual-writes and decommission old shards.
Tools like Vitess (used at YouTube), gh-ost (GitHub's online schema change tool), and pt-online-schema-change (Percona) automate portions of this process. For systems built on consistent hashing, adding a new node automatically triggers rebalancing of only the affected key ranges.
Critical considerations during resharding include maintaining application performance during backfill by throttling the copy rate. Test rollback procedures before starting because if anything goes wrong during cutover, you need to revert quickly. Coordinate with dependent services that may cache shard routing information. Plan for the resharding to take days or weeks for large datasets, not hours.
Follow-up questions:
- How would you handle resharding a database with 10TB of data while maintaining sub-100ms query latency?
- What happens if the application crashes during the dual-write phase?
- How do you verify data consistency between old and new shards when the data is constantly changing?
8. How do you handle schema migrations across a sharded database?
What the interviewer is really asking: Do you understand the operational challenges that multiply with sharding and can you plan migrations that do not cause downtime?
Answer framework:
Schema migrations on a sharded database are dramatically more complex than on a single database because the migration must be executed on every shard, failures on individual shards must be handled independently, and the application must be compatible with both the old and new schema during the rollout.
The safest approach is the expand-contract pattern, executed in three phases. Phase one, expand: add the new column, table, or index without removing anything. The application code still uses the old schema. This is backward compatible. Phase two, migrate: update the application to write to both old and new schema elements. Backfill existing data into the new schema elements. Phase three, contract: once all data is migrated and the application fully uses the new schema, remove the old schema elements.
For a sharded environment, execute each phase across all shards using a rolling approach. Migrate shards one at a time or in small batches. If a migration fails on one shard, you can fix it without affecting other shards. Monitor each shard's performance during and after migration.
For adding an index on a large sharded table, build the index concurrently on each shard using CREATE INDEX CONCURRENTLY in PostgreSQL or similar non-blocking DDL in MySQL. Stagger the index builds across shards to avoid overwhelming the cluster.
For column type changes, never alter the column in place. Instead, add a new column with the desired type, dual-write to both columns, backfill existing rows, switch reads to the new column, then drop the old column. This avoids table locks on large tables.
Automation is essential at scale. Build a migration orchestrator that tracks migration state per shard, handles retries, and provides visibility into progress. Companies like Stripe and Amazon have dedicated infrastructure teams that build and maintain these migration frameworks.
Follow-up questions:
- How do you roll back a schema migration that has been partially applied across shards?
- What if a migration takes 2 hours per shard and you have 500 shards?
- How do you ensure the application code handles both old and new schemas simultaneously?
9. What are the different sharding strategies for multi-tenant SaaS applications?
What the interviewer is really asking: Can you reason about the trade-offs between tenant isolation, resource efficiency, and operational complexity in a real-world business context?
Answer framework:
Multi-tenant sharding strategies exist on a spectrum from full sharing to full isolation. The right choice depends on the number of tenants, their size distribution, compliance requirements, and performance isolation needs.
Shared database, shared schema: all tenants live in the same tables with a tenant_id column. This is the most resource-efficient but provides no isolation. A poorly performing query from one tenant can affect all others. This works for applications with many small tenants of similar size.
Shared database, separate schemas: each tenant gets its own schema (set of tables) within a single database. This provides logical isolation and makes per-tenant operations like backup and restore easier. However, the database server is still shared, so resource contention is possible. Connection pooling is more complex because connections must be routed to the correct schema.
Shard per tenant (dedicated database per tenant): each tenant gets its own database on a potentially shared server. This provides strong isolation. Per-tenant performance monitoring, backup, and compliance are straightforward. This is the preferred approach for enterprise SaaS with strict compliance requirements. The downside is operational overhead of managing hundreds or thousands of databases.
The hybrid approach is most common in practice: small tenants share shards using a shared-schema approach with tenant_id, while large enterprise tenants get dedicated shards. Route queries based on a tenant directory that maps tenant_id to shard. This combines resource efficiency for the long tail of small tenants with isolation guarantees for large tenants.
Consider noisy neighbor mitigation regardless of strategy: implement per-tenant rate limiting, query timeout enforcement, and resource quotas. Monitor per-tenant query patterns and move problematic tenants to isolated shards proactively. Build the tenant routing layer with the ability to migrate individual tenants between shards without downtime.
Follow-up questions:
- How would you handle a tenant that suddenly grows from small to large?
- What compliance considerations affect sharding strategy for tenants in different countries?
- How do you implement cross-tenant analytics when tenants live on different shards?
10. How do you implement distributed unique ID generation in a sharded database?
What the interviewer is really asking: Do you understand why auto-increment breaks with sharding and can you evaluate alternatives based on their properties: uniqueness, ordering, size, and generation speed?
Answer framework:
Auto-increment IDs are local to a single database. With multiple shards, two shards can independently generate the same ID, causing collisions. Several strategies address this.
UUID v4: randomly generated 128-bit identifiers. Collision probability is astronomically low. No coordination between shards is needed. However, UUIDs are large (16 bytes vs 8 bytes for a 64-bit integer), poor for indexing (random values cause B-tree fragmentation and scattered I/O), and not sortable by creation time.
Snowflake IDs (originally from Twitter): 64-bit integers composed of a timestamp (41 bits, millisecond precision, 69 years of range), a machine ID (10 bits, 1024 machines), and a sequence number (12 bits, 4096 IDs per millisecond per machine). These are time-sortable (IDs generated later are larger), unique across machines without coordination, compact (8 bytes), and index-friendly. The trade-off is that machine IDs must be assigned centrally, and clock skew between machines can cause out-of-order IDs.
ULID (Universally Unique Lexicographically Sortable Identifier): similar to Snowflake but encoded as a 128-bit string that is lexicographically sortable. Uses 48 bits for timestamp and 80 bits for randomness. Compatible with UUID storage formats while being sortable.
Database sequence ranges: allocate ranges to each shard. Shard 1 gets IDs 1 to 1,000,000, shard 2 gets 1,000,001 to 2,000,000. Simple but requires a central allocator and creates ordering that leaks information about insert volume.
For most sharded systems, Snowflake-style IDs are the best default choice because they are compact, sortable, unique without coordination, and compatible with SQL and NoSQL databases. The implementation is simple enough that you do not need a separate service: embed the ID generation logic in the application layer.
Follow-up questions:
- How do Snowflake IDs handle clock skew between machines?
- What problems does UUID v4 cause for database index performance and how would you mitigate them?
- How would you migrate from auto-increment IDs to a distributed ID scheme in a running system?
11. How do you implement global secondary indexes in a sharded database?
What the interviewer is really asking: Can you solve the problem of querying sharded data by attributes other than the shard key without resorting to full scatter-gather on every query?
Answer framework:
When data is sharded by user_id but you need to look up records by email address, you face the global secondary index problem. The email could be on any shard, so a naive approach broadcasts the query to every shard and merges results. This does not scale.
There are two categories of global secondary indexes: local indexes and global indexes. A local secondary index is built per shard, covering only the data on that shard. Queries by the secondary index still require scatter-gather, but the index makes each shard's portion faster. This is what MongoDB calls a non-shard-key index.
A global secondary index is a separate data structure that maps secondary key values to shard locations. For example, a global index on email maps each email to the (shard, primary_key) where the record lives. Queries first consult the global index to find the target shard, then fetch the record directly. This converts scatter-gather into a two-hop lookup.
Implementing a global secondary index requires careful consideration of consistency. The index must be updated atomically with the base data. If the index is on a different shard than the data, this requires a distributed transaction or an eventually consistent approach where the index is updated asynchronously via change data capture. Stale indexes can return incorrect locations, so include a fallback to check other shards if the pointed-to shard does not have the record.
For high-throughput systems, consider a dedicated index service backed by Elasticsearch or similar technology. The index service consumes change events from all shards and maintains a global search index. This decouples the index from the sharding scheme entirely.
Google Spanner takes another approach: it supports global indexes natively by treating the index as a separate table that is itself sharded by the indexed column. Writes to the base table and index table are coordinated using Spanner's distributed transaction protocol.
Follow-up questions:
- How do you handle unique constraints across shards when the unique field is not the shard key?
- What is the latency impact of a global secondary index lookup versus a direct shard key lookup?
- How do you rebuild a corrupted global secondary index without downtime?
12. How would you shard a social graph database?
What the interviewer is really asking: Can you handle graph-structured data that inherently resists partitioning because any edge can cross a partition boundary?
Answer framework:
Social graph sharding is one of the hardest sharding problems because graphs have high connectivity: any user can be friends with any other user, and common operations like friend-of-friend queries can span many shards.
The simplest approach is to shard by user_id. Each shard stores a user's profile and their outgoing edges (follow/friend relationships). Looking up who a user follows is efficient because it hits one shard. But looking up who follows a user (incoming edges) requires scatter-gather unless you duplicate edges: store both the forward edge on the source shard and the reverse edge on the destination shard. This doubles edge storage but makes both directions efficient.
For friend-of-friend queries (two hops), the naive approach hits the user's shard to get friends, then fans out to every shard containing those friends. For a user with 500 friends spread across 100 shards, this generates 100 parallel queries. Mitigation strategies include caching popular users' friend lists in a distributed cache, pre-computing friend-of-friend lists for common recommendations, and limiting query depth and result count.
Graph partitioning algorithms like METIS can minimize cross-shard edges by placing densely connected subgraphs on the same shard. In a social network, friend groups tend to cluster geographically and socially, so community-aware partitioning reduces cross-shard traffic. However, the partition must be recomputed periodically as the graph evolves.
Facebook's TAO is the canonical example of a sharded social graph. It uses a two-level caching architecture in front of a sharded MySQL backend. Objects and associations are cached at the edge, with a leader-follower cache hierarchy that provides read-after-write consistency. The key insight is that most social graph queries are simple traversals (fetch friends, fetch timeline) that can be served from cache without touching the database.
For systems requiring more complex graph queries like shortest path or community detection, consider a dedicated graph database like Neo4j for the analytical workload while keeping the transactional social graph in a sharded relational store.
Follow-up questions:
- How do you handle the case where one user has 10 million followers and their data becomes a hotspot?
- How would you implement mutual friend computation efficiently across shards?
- What consistency model would you use for the social graph and why?
13. What are the consistency challenges introduced by sharding and how do you address them?
What the interviewer is really asking: Do you have a deep understanding of distributed consistency models and can you apply the CAP theorem to practical sharding decisions?
Answer framework:
Sharding introduces several consistency challenges that do not exist in a single-node database. The most fundamental is that ACID transactions are local to a shard. A transaction that reads from shard A and writes to shard B requires coordination that introduces latency, reduces availability, and increases complexity.
Distributed transaction consistency: as discussed earlier, two-phase commit provides strong consistency across shards but at the cost of availability and performance. In many systems, this is an acceptable trade-off for financial transactions but not for social media feeds. The saga pattern provides eventual consistency with explicit compensation logic. Choose the consistency model based on the business requirements of each operation, not a blanket rule.
Read-your-writes consistency: after a user writes data to shard A, subsequent reads must see that write. If reads can be routed to a different replica of shard A, stale data might be returned. Solutions include session stickiness (route all requests from a session to the same replica), reading from the leader replica for the shard, or including a write timestamp in the session and only reading from replicas that have caught up to that timestamp.
Cross-shard referential integrity: if user data is on shard A and order data is on shard B, a foreign key constraint from orders to users cannot be enforced by the database. Options include enforcing referential integrity in the application layer, using soft deletes instead of hard deletes to avoid dangling references, and accepting eventual consistency with periodic reconciliation jobs that detect and fix inconsistencies.
Monotonic reads: a client should not see a value go backward in time. If read requests are load-balanced across replicas with different replication lag, this can happen. Ensure that within a session, reads for the same shard key go to the same replica.
For systems where strong cross-shard consistency is essential, consider databases that provide it natively like Google Spanner or CockroachDB. These databases shard data automatically and use distributed consensus to maintain strong consistency across shards, abstracting away much of the complexity discussed above.
Follow-up questions:
- How do you implement causal consistency across shards?
- What monitoring would you set up to detect consistency violations in a sharded system?
- When is eventual consistency acceptable and how do you communicate this to product stakeholders?
14. How do you design a sharding strategy for a system like Uber or Lyft?
What the interviewer is really asking: Can you apply sharding concepts to a geospatial, real-time system with complex access patterns and stringent latency requirements?
Answer framework:
A ride-sharing system like Uber or Lyft has multiple data domains that require different sharding strategies. The key insight is that no single sharding scheme works for all data types.
For rider and driver profiles, shard by user_id using hash-based sharding. Access patterns are dominated by point lookups on user_id, and the data distributes evenly. These are relatively straightforward.
For trip data, shard by trip_id (hash-based). Each trip is an independent entity accessed by its ID. For rider trip history, maintain a secondary index from rider_id to trip_ids, co-located on the rider's shard. Similarly for driver trip history.
For real-time driver locations, geographic sharding is essential. Divide the service area into geospatial cells using a system like geohashing or S2 cells. Each cell maps to a shard. When a rider requests a ride, the system queries the shard for the rider's cell and adjacent cells to find nearby available drivers. This keeps geospatial queries local. The challenge is that cell boundaries can split dense areas like downtown, and drivers constantly move between cells. Use overlapping cells or query adjacent cells to handle boundary effects.
For the supply-demand matching engine, shard by geographic region. Each region runs an independent matching service that pairs riders with drivers. This reduces contention and keeps matching latency low. Cross-region trips where pickup and dropoff are in different regions are handled by the pickup region's matcher.
For pricing and surge data, shard by geographic zone. Surge pricing is computed per zone based on local supply-demand ratios. Sharding by zone keeps the pricing computation local.
The overall architecture uses distributed systems principles: each data domain has its own sharded store optimized for its access patterns. A service mesh routes requests to the correct shard. Geographic sharding requires special handling for rebalancing because city populations shift and new cities are added regularly.
Follow-up questions:
- How do you handle a new city launch where you need to rapidly provision sharding infrastructure?
- What happens when a driver crosses a geoshard boundary during a trip?
- How do you ensure consistent pricing when surge calculations happen on different shards?
15. What are the alternatives to traditional sharding and when would you choose them?
What the interviewer is really asking: Is your toolkit broader than just sharding? Do you evaluate multiple approaches and choose the one that best fits the constraints?
Answer framework:
Sharding is a powerful technique, but it is not the only way to scale a database. Understanding the alternatives helps you make better decisions and sometimes avoid the complexity of sharding entirely.
Read replicas: for read-heavy workloads, adding replicas that serve read traffic can scale reads horizontally without sharding. The primary handles all writes, and replicas asynchronously replicate. This works well when the write volume fits on a single node and the read-to-write ratio is high (10:1 or more). The limitation is replication lag, which means reads may be stale. This approach is deeply related to how database replication works.
Partitioned tables (single-node partitioning): PostgreSQL and MySQL both support table partitioning where a table is divided into partitions stored on the same server. This improves query performance for range queries and makes maintenance operations (like dropping old data) faster. It does not provide horizontal scaling but can delay the need for sharding by improving single-node efficiency.
NewSQL databases: CockroachDB, Google Spanner, TiDB, and YugabyteDB provide automatic sharding with distributed ACID transactions. They abstract away shard key selection, rebalancing, and cross-shard transactions. The trade-off is higher per-query latency compared to a well-optimized single-shard query, operational complexity of running a distributed database, and potential vendor lock-in.
CQRS with event sourcing: separate the write path and read path entirely. Writes go to an event log, and read-optimized projections are built from the event stream. The write store and read store can use completely different technologies and scaling strategies. This is especially powerful when combined with a message queue like Kafka for the event stream.
Application-level sharding versus middleware: you can implement sharding logic in the application code, use a proxy like ProxySQL or Vitess, or use a database that shards natively. Application-level gives the most control, middleware reduces application complexity, and native sharding provides the most seamless experience.
The decision tree: start with a single database with proper indexing and query optimization. Add caching. Add read replicas. Only then consider sharding if write throughput or storage exceeds single-node capacity. If you need distributed transactions, evaluate NewSQL before building custom sharding.
Follow-up questions:
- When would you choose CockroachDB over manually sharding PostgreSQL?
- How does CQRS interact with sharding if you need both?
- What are the cost implications of these different approaches at scale?
Common Mistakes in Database Sharding Interviews
-
Proposing sharding as the first solution. Interviewers want to see that you exhaust simpler approaches first. Always discuss vertical scaling, read replicas, caching, and query optimization before introducing sharding. Demonstrate that you understand sharding is a last resort, not a default.
-
Choosing a shard key without analyzing query patterns. The shard key must align with the dominant access pattern. Selecting a shard key based on data distribution alone, without considering how the application queries data, leads to scatter-gather queries that negate the benefits of sharding.
-
Ignoring cross-shard operations. Many candidates design a clean sharding scheme for the primary access pattern but fail to address secondary queries, joins, and transactions that cross shard boundaries. Always enumerate the key query patterns and evaluate each against the proposed sharding scheme.
-
Underestimating operational complexity. Sharding multiplies every operational task: monitoring, backups, schema migrations, failover, capacity planning. Failing to discuss these operational implications signals a lack of production experience.
-
Treating sharding as a one-time decision. Data patterns change, traffic grows unevenly, and new features introduce new query patterns. A good sharding design includes a strategy for resharding, shard splitting, and evolving the sharding scheme over time.
How to Prepare for Database Sharding Interviews
Start by building a strong conceptual foundation. Understand consistent hashing, the CAP theorem, distributed transaction protocols, and the properties of different database engines. Read engineering blogs from companies that operate at massive scale, including Google and Amazon, to understand how they approach sharding in practice.
Next, practice applying sharding to concrete systems. Design the sharding strategy for a social media platform, an e-commerce marketplace, a messaging system, and a real-time analytics pipeline. For each, go through the complete exercise: choose the shard key, evaluate distribution, identify cross-shard operations, plan for resharding, and discuss operational requirements. Our system design interview guide provides a structured framework for this practice.
Build hands-on experience by setting up a sharded database locally using Vitess, CockroachDB, or MongoDB. Run queries against it, observe how cross-shard operations differ from single-shard operations, and experiment with adding and removing shards. Hands-on experience gives you the confidence and vocabulary that interviewers recognize.
Finally, practice articulating trade-offs under time pressure. In a 45-minute interview, you need to quickly assess the sharding requirements, propose a strategy, and discuss its implications. Time yourself explaining a sharding design in 5 minutes, then go deeper on specific aspects when prompted. Explore the learning paths and check out our pricing for structured interview preparation.
Related Resources
GO DEEPER
Master this topic in our 12-week cohort
Our Advanced System Design cohort covers this and 11 other deep-dive topics with live sessions, assignments, and expert feedback.