Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
LaravelPHPJune 22, 20264 min read

Laravel Database Sharding: Implementing Deterministic Horizontal Partitioning

Laravel database sharding allows you to scale beyond single-instance limits. Learn how to implement horizontal partitioning using custom connection resolvers.

LaravelPHPDatabaseShardingScalabilityArchitectureEloquentBackend

When your primary database instance starts hitting IOPS limits during peak traffic, vertical scaling stops being an option. We faced this last year while supporting a multi-tenant system that grew to roughly 40 million rows across our core activity tables; the indexes were bloated, and query times started creeping past 300ms. If you’ve reached this point, you’re ready to look at Database Sharding for High-Concurrency: A Practical Scaling Guide to understand the broader strategy before writing a single line of code.

The Strategy: Deterministic Routing

Horizontal partitioning isn't about just splitting tables; it’s about deterministic routing. You need a way to look at a tenant_id or user_id and know exactly which database connection to use. We initially tried a round-robin approach, but it turned into a nightmare for reporting and cross-shard joins. We switched to a hash-based deterministic routing strategy.

By mapping a shard key to a specific connection name in your config/database.php, you keep the logic predictable. Here is how we implemented a custom connection resolver in Laravel 10.

First, define your shards in the configuration:

PHP
'connections' => [
    'shard_0' => [ #6A9955">/* ... */ ],
    'shard_1' => [ #6A9955">/* ... */ ],
],

Implementing Laravel Database Sharding with Resolvers

To make this feel native, I prefer extending the model's connection logic rather than manually setting the connection every time. We created a Shardable trait that hooks into the model's getConnectionName method.

PHP
trait Shardable {
    public function getConnectionName() {
        $shardId = $this->resolveShardId();
        return "shard_{$shardId}";
    }

    protected function resolveShardId() {
        #6A9955">// Deterministic hash: user_id % total_shards
        return (int) $this->shard_key % 2; 
    }
}

This works great for individual model instances, but it fails when you try to perform bulk queries or migrations. You’ll need to iterate through your registered shards explicitly. If you're struggling with complex filtering logic, you might want to review Mastering Laravel Eloquent Scopes: Writing Reusable Query Constraints to ensure your constraints remain clean when applied across different connections.

The Pitfalls of Horizontal Partitioning

We learned the hard way that horizontal partitioning introduces significant complexity in global queries. If you need to fetch "all active users" across the entire system, you can’t just run one query. You have to aggregate results from every shard.

We first tried using standard UNION ALL queries, but the latency hit was unacceptable because we were waiting for the slowest shard to respond. We ended up using a Parallel job execution approach to query shards concurrently.

PHP
$shards = ['shard_0', 'shard_1'];
$results = collect($shards)->map(function ($shard) {
    return DB::connection($shard)->table('users')->where('active', 1)->get();
})->flatten();

This is fine for small datasets, but for high-concurrency needs, you should consider the raw performance gains discussed in Laravel Query Builder: Build Complex Database Queries Without Eloquent. Eloquent’s hydration overhead becomes a bottleneck when you’re pulling thousands of records from four different connections at once.

Managing Connections and Scalability

Database scalability isn't just about splitting the data; it's about connection management. PHP-FPM processes will quickly exhaust your connection limits if every request opens a new connection to every shard.

Ensure your database.php config uses persistent => true where applicable, or use a tool like ProxySQL to multiplex connections before they reach your database. We found that without a proxy, our database server was spending more time performing the TCP handshake than actually executing the SQL.

What I'd Do Differently

Looking back, we hardcoded the shard logic too deeply into our models. If I were starting over, I’d use a dedicated ShardManager service that acts as a singleton. This would allow us to swap the routing logic—for example, moving from a modulo-based hash to a lookup table—without touching fifty different Eloquent models.

I’m still not entirely happy with how we handle migrations across shards. Right now, we run them sequentially using a custom Artisan command. It works, but it's slow. If one shard fails, you’re left with a partially migrated system, which is a production nightmare. We’re currently exploring atomic migration strategies, but that’s a topic for another deep dive.

Horizontal partitioning is a powerful tool, but it's a massive shift in how your application handles data. Don't reach for it until you've exhausted indexing, caching, and read-replicas. When you do take the leap, keep your routing logic deterministic and your connection management centralized.

Back to Blog

Similar Posts

LaravelPHPJune 22, 20264 min read

Laravel Read-Write Splitting: Deterministic Connection Routing Guide

Master Laravel read-write splitting with deterministic connection routing. Scale your database performance and high availability without complex external proxies.

Read more
From below of monitor of modern computer with opened files on blue screen
Laravel
PHP
June 21, 2026
4 min read

Laravel Database Replication for Multi-Region Data Consistency

Laravel database replication helps scale globally. Learn how to manage read-replicas and solve data consistency challenges in distributed systems effectively.

Read more
Closeup photo of a textured red brick wall showcasing a detailed pattern with natural color variations.
LaravelPHPJune 21, 20264 min read

Transactional Outbox Pattern in Laravel: Ensuring Data Consistency

Master the Transactional Outbox pattern in Laravel to prevent data loss. Learn how to bridge database transactions and event dispatching for reliable systems.

Read more