PHPackages                             morozmkhl/scalable-db - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. morozmkhl/scalable-db

ActiveLibrary[Database &amp; ORM](/categories/database)

morozmkhl/scalable-db
=====================

Advanced sharding, replication &amp; fail‑over package for Laravel 11

v2.0.0(1mo ago)31MITPHPPHP ^8.2CI passing

Since Sep 6Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/morozmkhl/scalable-db)[ Packagist](https://packagist.org/packages/morozmkhl/scalable-db)[ Docs](https://github.com/morozmkhl/scalable-db)[ RSS](/packages/morozmkhl-scalable-db/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (9)Versions (4)Used By (0)

ScalableDB
==========

[](#scalabledb)

Shard routing layer for Laravel 11 applications. The package resolves a tenant or entity key to a database shard, switches the default connection for the duration of a callback or HTTP request, and provides optional fail-over and operational CLI commands.

[![Tests](https://github.com/morozmkhl/scalable-db/actions/workflows/ci.yml/badge.svg)](https://github.com/morozmkhl/scalable-db/actions/workflows/ci.yml)

Requirements
------------

[](#requirements)

ComponentVersionPHP^8.2Laravel^11.5Installation
------------

[](#installation)

```
composer require morozmkhl/scalable-db
php artisan vendor:publish --tag=scalable-db-config
```

Optional publish targets:

```
php artisan vendor:publish --tag=scalable-db-migrations
php artisan vendor:publish --tag=scalable-db-database
```

The `scalable-db-database` tag provides a sample `database-shards.php` stub with read/write host configuration.

Configuration
-------------

[](#configuration)

Publish `config/scalable-db.php` and define shard connections in `config/database.php`. Each shard entry maps a logical name to a Laravel connection name and an optional list of replica connections used during fail-over.

```
return [
    'default_strategy' => 'hash',

    'strategies' => [
        'hash' => [
            'shard_count' => 2,
            'map' => [0 => 'shard_0', 1 => 'shard_1'],
        ],
    ],

    'shards' => [
        'shard_0' => [
            'connection' => 'shard0_master',
            'replicas' => ['shard0_replica1'],
        ],
        'shard_1' => [
            'connection' => 'shard1_master',
            'replicas' => [],
        ],
    ],

    'failover' => [
        'auto_failover' => false,
        'max_retries' => 1,
        'fallback_connection' => null,
    ],
];
```

Fail-over is disabled by default. Set `auto_failover` to `true` to enable replica retry on `PDOException`.

Further reference: [Configuration](docs/configuration.md).

Sharding strategies
-------------------

[](#sharding-strategies)

### Hash

[](#hash)

Assigns keys using `crc32((string) $key) % shard_count` and a slot-to-shard map.

```
'strategies' => [
    'hash' => [
        'shard_count' => 2,
        'map' => [0 => 'shard_0', 1 => 'shard_1'],
    ],
],
'default_strategy' => 'hash',
```

```
use ScalableDB\Facades\Shard;

Shard::forTenant($userId)->run(function () use ($userId) {
    return User::find($userId);
});
```

### Range

[](#range)

Assigns keys by inclusive numeric ranges.

```
'strategies' => [
    'range' => [
        'ranges' => [
            ['min' => 1,     'max' => 10000,  'shard' => 'shard_0'],
            ['min' => 10001, 'max' => 20000,  'shard' => 'shard_1'],
        ],
    ],
],
'default_strategy' => 'range',
```

```
Shard::forTenant($orderId)->run(function () use ($orderId) {
    return Order::find($orderId);
});
```

### Lookup

[](#lookup)

Resolves keys from a lookup table (for example, `tenants`). Supports optional query result caching.

```
'strategies' => [
    'lookup' => [
        'connection'   => 'lookup',
        'table'        => 'tenants',
        'key_column'   => 'id',
        'shard_column' => 'shard',
        'cache_ttl'    => 300,
    ],
],
'default_strategy' => 'lookup',
```

```
Shard::forTenant($tenantId)->run(function () use ($tenantId) {
    return Post::where('tenant_id', $tenantId)->get();
});
```

Strategy details: [Sharding strategies](docs/strategies.md).

Read/write splitting
--------------------

[](#readwrite-splitting)

ScalableDB does not implement read/write routing. Configure `read`, `write`, and `sticky` on each shard connection in `config/database.php` using Laravel's built-in behaviour. The package switches the default connection to the shard master; Laravel routes individual statements to read or write hosts within that connection.

```
'shard0_master' => [
    'driver' => 'mysql',
    'read'   => ['host' => ['replica1.example.com']],
    'write'  => ['host' => ['master.example.com']],
    'sticky' => true,
],
```

Optional helpers select the read or write PDO for the current connection:

```
Shard::forTenant($id)->forRead()->run(fn () => User::find($id));
Shard::forTenant($id)->forWrite()->run(fn () => User::create([...]));
```

HTTP middleware
---------------

[](#http-middleware)

Register routes behind the `shard.tenant` middleware alias. The middleware resolves a tenant identifier in the following order:

1. `$request->user()->tenant_id`, or `$request->user()->id` when `tenant_id` is absent
2. HTTP header `X-Tenant-ID`
3. Query parameter `tenant_id`

If no tenant identifier is present, the request proceeds without changing the active shard.

```
Route::middleware('shard.tenant')->group(function () {
    Route::get('/posts', [PostController::class, 'index']);
});
```

Artisan commands
----------------

[](#artisan-commands)

CommandDescription`php artisan shard:migrate [--shard=NAME] [--path=PATH]`Run migrations on all shards or one shard`php artisan shard:seed`Run the configured seeder class`php artisan shard:status`Report connectivity for masters and replicas`php artisan shard:diagnose [--json]`Full diagnostics; exit code `1` on failureCommand reference: [CLI](docs/cli.md).

Events
------

[](#events)

EventDispatched when`ShardResolved`A shard name is resolved from a tenant key`ShardFailover`Fail-over switches from master to a replica or fallback connection```
use ScalableDB\Events\ShardFailover;
use Illuminate\Support\Facades\Event;

Event::listen(ShardFailover::class, function (ShardFailover $event) {
    logger()->warning("Fail-over {$event->shard}: {$event->fromConnection} -> {$event->toConnection}", [
        'error' => $event->exception->getMessage(),
    ]);
});
```

Telescope
---------

[](#telescope)

[Laravel Telescope](https://laravel.com/docs/telescope) is an optional dependency. When present, the package registers a watcher that tags entries with `shard:` based on the active shard context.

Testing
-------

[](#testing)

```
composer test
composer lint -- --test
composer analyse
```

The test suite uses [Pest](https://pestphp.com/) and [Orchestra Testbench](https://packages.tools/testbench/). CI runs lint, static analysis, a PHP 8.2/8.4 × SQLite/MySQL matrix, and a Docker demo smoke test.

Demo environment
----------------

[](#demo-environment)

A Docker-based demo application is provided under `demo/`.

```
cd demo
docker compose up -d --build
curl http://localhost:8000/ping
curl -X POST -d "id=5&name=Eve" http://localhost:8000/users
curl http://localhost:8000/users/shard/5
```

See [Demo](docs/demo.md).

Limitations
-----------

[](#limitations)

- **Single-shard scope.** Queries run against one shard per callback or request. Cross-shard joins, aggregates, and transactions are not supported.
- **Fail-over trigger.** Fail-over reacts to `PDOException` only. Application-level errors and connection timeouts outside PDO are not handled automatically.
- **Fail-over default.** `auto_failover` is `false` by default; replica retry must be enabled explicitly.
- **Replica writes.** Fail-over may route traffic to a read-only replica. Write operations against a replica can fail at the database level.
- **No rebalancing.** The package does not migrate data between shards or rebalance keys.
- **No distributed transactions.** Two-phase commit and saga patterns are out of scope.
- **Replication setup.** MySQL (or other) replication must be configured manually in `config/database.php`.
- **Strategy binding.** `ShardManager` is registered as a singleton. Changing `default_strategy` at runtime requires `app()->forgetInstance('shard.manager')`.

Documentation
-------------

[](#documentation)

Full documentation is in [docs/](docs/README.md): installation, configuration, architecture, API, CLI, and development notes.

Contributing
------------

[](#contributing)

Run the following before opening a pull request:

```
composer lint -- --test
composer analyse
composer test
```

Code style is enforced with [Laravel Pint](https://laravel.com/docs/pint). Static analysis uses [PHPStan](https://phpstan.org/) with [Larastan](https://github.com/larastan/larastan).

License
-------

[](#license)

The MIT License. See [LICENSE](LICENSE).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~155 days

Total

3

Last Release

49d ago

Major Versions

v1.1.2 → v2.0.02026-07-12

### Community

Maintainers

![](https://www.gravatar.com/avatar/2661b6d872c2b4baa342ea89fd96cb40d19b4a0f9d6e2d99f57edc659f3d519d?d=identicon)[morozmkhl](/maintainers/morozmkhl)

---

Top Contributors

[![morozmkhl](https://avatars.githubusercontent.com/u/115979364?v=4)](https://github.com/morozmkhl "morozmkhl (13 commits)")

---

Tags

laraveldatabasereplicationshardingfailover

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/morozmkhl-scalable-db/health.svg)

```
[![Health](https://phpackages.com/badges/morozmkhl-scalable-db/health.svg)](https://phpackages.com/packages/morozmkhl-scalable-db)
```

###  Alternatives

[anourvalar/eloquent-serialize

Laravel Query Builder (Eloquent) serialization

11228.1M38](/packages/anourvalar-eloquent-serialize)[statamic-rad-pack/runway

Eloquently manage your database models in Statamic.

138249.0k8](/packages/statamic-rad-pack-runway)[ecotone/laravel

Ecotone for Laravel — CQRS, Event Sourcing, Sagas, Durable Workflows, and Outbox on top of Laravel Queue, via PHP attributes.

21336.4k4](/packages/ecotone-laravel)[ramadan/custom-fresh

A Laravel package to specify the tables that you do not want to drop while refreshing the database.

613.1k](/packages/ramadan-custom-fresh)[ramadan/easy-model

A Laravel package for enjoyably managing database queries.

111.6k](/packages/ramadan-easy-model)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
