replication-sharding-knowledge
Replication and Sharding knowledge base. Provides read/write splitting at application level, connection wrapper patterns, replica lag handling, and query routing for database scaling audits.
Best use case
replication-sharding-knowledge is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Replication and Sharding knowledge base. Provides read/write splitting at application level, connection wrapper patterns, replica lag handling, and query routing for database scaling audits.
Teams using replication-sharding-knowledge should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/replication-sharding-knowledge/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How replication-sharding-knowledge Compares
| Feature / Agent | replication-sharding-knowledge | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Replication and Sharding knowledge base. Provides read/write splitting at application level, connection wrapper patterns, replica lag handling, and query routing for database scaling audits.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Replication and Sharding Knowledge Base
Quick reference for application-level read/write splitting, connection routing, and replica lag handling in PHP applications.
## Master-Slave (Primary-Replica) Overview
```
┌─────────────────────────────────────────────────────────────────────┐
│ PRIMARY-REPLICA READ/WRITE SPLIT │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Application Layer │
│ │ │
│ ├── INSERT / UPDATE / DELETE ──▶ Primary (Master) │
│ │ │ │
│ │ Replication (async) │
│ │ │ │
│ │ ┌──────────┼──────────┐ │
│ │ │ │ │ │
│ │ ▼ ▼ ▼ │
│ └── SELECT ──────────▶ Replica 1 Replica 2 Replica 3 │
│ (round-robin) │
│ │
│ Benefits: │
│ • Read throughput scales linearly with replica count │
│ • Primary handles only writes → reduced write latency │
│ • Replicas can be in different regions → lower read latency │
│ │
│ Trade-offs: │
│ • Replication lag: replicas may return stale data │
│ • Write scaling requires sharding (replicas don't help) │
│ • Application must be aware of routing │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
## Connection Wrapper Pattern
Route SELECT queries to replicas, INSERT/UPDATE/DELETE to primary.
```php
<?php
declare(strict_types=1);
namespace Infrastructure\Database;
final class ReadWriteConnection
{
private ?\PDO $primaryConnection = null;
private ?\PDO $replicaConnection = null;
private bool $forcePrimary = false;
/**
* @param list<array{host: string, port: int}> $replicaConfigs
*/
public function __construct(
private readonly ConnectionConfig $primaryConfig,
private readonly array $replicaConfigs,
private readonly string $database,
private readonly string $username,
private readonly string $password,
) {}
public function primary(): \PDO
{
if ($this->primaryConnection === null) {
$this->primaryConnection = $this->connect(
$this->primaryConfig->host,
$this->primaryConfig->port,
);
}
return $this->primaryConnection;
}
public function replica(): \PDO
{
if ($this->forcePrimary) {
return $this->primary();
}
if ($this->replicaConnection === null) {
$config = $this->replicaConfigs[array_rand($this->replicaConfigs)];
$this->replicaConnection = $this->connect($config['host'], $config['port']);
}
return $this->replicaConnection;
}
public function usePrimary(): void
{
$this->forcePrimary = true;
}
public function releasePrimary(): void
{
$this->forcePrimary = false;
}
private function connect(string $host, int $port): \PDO
{
$dsn = sprintf('pgsql:host=%s;port=%d;dbname=%s', $host, $port, $this->database);
return new \PDO($dsn, $this->username, $this->password, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
]);
}
}
```
## Query Routing Decision Tree
```
┌─────────────────────────────────────────────────────────────────────┐
│ QUERY ROUTING DECISION TREE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Incoming Query │
│ │ │
│ ▼ │
│ Inside transaction? │
│ │ │
│ ├── YES ──▶ Route to PRIMARY (all queries in TX go to master) │
│ │ │
│ └── NO │
│ │ │
│ ▼ │
│ Is write query? (INSERT/UPDATE/DELETE/DDL) │
│ │ │
│ ├── YES ──▶ Route to PRIMARY │
│ │ │ │
│ │ ▼ │
│ │ Set "sticky master" flag │
│ │ (next reads go to primary for N seconds) │
│ │ │
│ └── NO (SELECT) │
│ │ │
│ ▼ │
│ "Sticky master" active? │
│ │ │
│ ├── YES ──▶ Route to PRIMARY (read-your-writes) │
│ │ │
│ └── NO │
│ │ │
│ ▼ │
│ Critical read? (consistency required) │
│ │ │
│ ├── YES ──▶ Route to PRIMARY │
│ │ │
│ └── NO ──▶ Route to REPLICA (round-robin) │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
## Replica Lag Handling
### Strategies
| Strategy | Description | Consistency | Complexity |
|----------|-------------|-------------|------------|
| Sticky master | After write, read from master for N seconds | Strong (within window) | Low |
| Causal consistency token | Pass replication position to reader | Strong | Medium |
| Read from master | Critical reads always go to master | Strong | Low |
| Lag-aware routing | Check replica lag, fallback to master | Near-real-time | High |
| Eventual reads | Accept stale data | Eventual | None |
### Sticky Master Implementation
```php
<?php
declare(strict_types=1);
namespace Infrastructure\Database;
final class StickyMasterConnection
{
private ?\DateTimeImmutable $lastWriteAt = null;
public function __construct(
private readonly ReadWriteConnection $connection,
private readonly int $stickyDurationSeconds = 5,
) {}
public function executeWrite(string $sql, array $params = []): void
{
$stmt = $this->connection->primary()->prepare($sql);
$stmt->execute($params);
$this->lastWriteAt = new \DateTimeImmutable();
}
public function executeRead(string $sql, array $params = []): array
{
$pdo = $this->shouldUsePrimary()
? $this->connection->primary()
: $this->connection->replica();
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
private function shouldUsePrimary(): bool
{
if ($this->lastWriteAt === null) {
return false;
}
$elapsed = (new \DateTimeImmutable())->getTimestamp() - $this->lastWriteAt->getTimestamp();
return $elapsed < $this->stickyDurationSeconds;
}
}
```
### Lag-Aware Routing
```php
<?php
declare(strict_types=1);
namespace Infrastructure\Database;
final readonly class LagAwareRouter
{
public function __construct(
private ReadWriteConnection $connection,
private float $maxAcceptableLagSeconds = 1.0,
) {}
public function selectReplica(): \PDO
{
$lag = $this->measureReplicaLag();
if ($lag > $this->maxAcceptableLagSeconds) {
return $this->connection->primary();
}
return $this->connection->replica();
}
private function measureReplicaLag(): float
{
// PostgreSQL: check replication lag
$stmt = $this->connection->replica()->query(
"SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) AS lag_seconds"
);
$row = $stmt->fetch();
return (float) ($row['lag_seconds'] ?? PHP_FLOAT_MAX);
}
}
```
## Transaction-Aware Routing
All queries inside a transaction must go to the primary to maintain ACID guarantees.
```php
<?php
declare(strict_types=1);
namespace Infrastructure\Database;
final class TransactionAwareConnection
{
private bool $inTransaction = false;
public function __construct(
private readonly ReadWriteConnection $connection,
) {}
public function beginTransaction(): void
{
$this->connection->primary()->beginTransaction();
$this->inTransaction = true;
$this->connection->usePrimary();
}
public function commit(): void
{
$this->connection->primary()->commit();
$this->inTransaction = false;
$this->connection->releasePrimary();
}
public function rollBack(): void
{
$this->connection->primary()->rollBack();
$this->inTransaction = false;
$this->connection->releasePrimary();
}
public function query(string $sql, array $params = []): array
{
$pdo = $this->resolveConnection($sql);
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
private function resolveConnection(string $sql): \PDO
{
if ($this->inTransaction) {
return $this->connection->primary();
}
if ($this->isWriteQuery($sql)) {
return $this->connection->primary();
}
return $this->connection->replica();
}
private function isWriteQuery(string $sql): bool
{
$normalized = strtoupper(ltrim($sql));
return str_starts_with($normalized, 'INSERT')
|| str_starts_with($normalized, 'UPDATE')
|| str_starts_with($normalized, 'DELETE')
|| str_starts_with($normalized, 'CREATE')
|| str_starts_with($normalized, 'ALTER')
|| str_starts_with($normalized, 'DROP')
|| str_starts_with($normalized, 'TRUNCATE');
}
}
```
## Framework Integration Examples
### Doctrine DBAL PrimaryReadReplicaConnection
```php
<?php
declare(strict_types=1);
// config/packages/doctrine.yaml equivalent
// Doctrine DBAL natively supports primary-replica via PrimaryReadReplicaConnection
$connectionParams = [
'wrapperClass' => \Doctrine\DBAL\Connections\PrimaryReadReplicaConnection::class,
'driver' => 'pdo_pgsql',
'primary' => [
'host' => 'db-primary',
'port' => 5432,
'dbname' => 'myapp',
'user' => 'app',
'password' => 'secret',
],
'replica' => [
[
'host' => 'db-replica1',
'port' => 5432,
'dbname' => 'myapp',
'user' => 'app_readonly',
'password' => 'secret',
],
[
'host' => 'db-replica2',
'port' => 5432,
'dbname' => 'myapp',
'user' => 'app_readonly',
'password' => 'secret',
],
],
];
// Usage: Doctrine automatically routes reads to replicas
// $connection->ensureConnectedToPrimary(); // force primary for critical reads
```
### Laravel Read/Write Configuration
```php
<?php
declare(strict_types=1);
// config/database.php — Laravel read/write split
return [
'connections' => [
'pgsql' => [
'read' => [
'host' => [
env('DB_READ_HOST_1', 'db-replica1'),
env('DB_READ_HOST_2', 'db-replica2'),
],
],
'write' => [
'host' => env('DB_WRITE_HOST', 'db-primary'),
],
'driver' => 'pgsql',
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'myapp'),
'username' => env('DB_USERNAME', 'app'),
'password' => env('DB_PASSWORD', ''),
'sticky' => true, // sticky master after writes
],
],
];
```
## Quick Reference Tables
### Routing Rules Summary
| Query Type | Transaction Active | After Recent Write | Route To |
|------------|-------------------|-------------------|----------|
| SELECT | No | No | Replica |
| SELECT | No | Yes (< N sec) | Primary (sticky) |
| SELECT | Yes | — | Primary |
| SELECT FOR UPDATE | — | — | Primary |
| INSERT/UPDATE/DELETE | — | — | Primary |
| DDL (CREATE/ALTER) | — | — | Primary |
### Replication Topology Comparison
| Topology | Write Scaling | Read Scaling | Failover | Complexity |
|----------|--------------|-------------|----------|------------|
| Single primary, N replicas | No (1 writer) | Yes (N readers) | Manual/auto | Low |
| Multi-primary | Yes (N writers) | Yes (N readers) | Automatic | High |
| Cascading replicas | No | Yes (tree) | Complex | Medium |
| Circular replication | Limited | Yes | Complex | High |
### Common Pitfalls
| Pitfall | Problem | Solution |
|---------|---------|----------|
| All reads to primary | No read scaling benefit | Route SELECTs to replicas |
| Ignoring replica lag | Stale data in critical reads | Sticky master or read from primary |
| No fallback on replica failure | Read failures | Health check + fallback to primary |
| `SELECT FOR UPDATE` on replica | Lock not acquired | Always route locking reads to primary |
| Large transactions hold master | Blocks replication | Keep transactions short |
| No connection timeout | Hung connections | Set `connect_timeout` and `statement_timeout` |
## Detection Patterns
```bash
# Read/write split configuration
Grep: "read.*write|write.*read|PrimaryReadReplica|MasterSlave" --glob "**/*.php"
Grep: "read.*host|write.*host|DB_READ_HOST|DB_WRITE_HOST" --glob "**/.env*"
# Doctrine primary-replica
Grep: "PrimaryReadReplicaConnection|MasterSlaveConnection" --glob "**/*.php"
Grep: "ensureConnectedToPrimary|ensureConnectedToReplica" --glob "**/*.php"
# Laravel read/write config
Grep: "'read'.*=>|'write'.*=>|'sticky'.*=>.*true" --glob "**/database.php"
# Manual routing patterns
Grep: "primary\(\)|replica\(\)|master\(\)|slave\(\)" --glob "**/*.php"
Grep: "isWriteQuery|isReadQuery|routeQuery" --glob "**/*.php"
# Replication lag monitoring
Grep: "pg_last_xact_replay_timestamp|Seconds_Behind_Master|replication_lag" --glob "**/*.php"
# Connection configuration
Grep: "PDO::ATTR_PERSISTENT|ATTR_PERSISTENT" --glob "**/*.php"
Grep: "pgbouncer|proxysql" --glob "**/docker-compose*.yml"
```
## References
For detailed information, load these reference files:
- `references/read-write-patterns.md` — Doctrine DBAL PrimaryReadReplicaConnection setup, custom connection wrapper, Laravel read_write config, transaction-aware routing, replica lag detection, health checksRelated Skills
yii-knowledge
Yii framework knowledge base. Provides Yii3 modular architecture, DDD integration, PSR-7/PSR-15 compliance, persistence, DI, security (RBAC, auth), event system (PSR-14), queue/jobs, infrastructure components (cache, rate limiter, HTTP client), testing, and antipatterns for Yii PHP projects.
testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
task-progress-knowledge
TaskCreate pattern guidelines for progress tracking in coordinator agents
symfony-knowledge
Symfony framework knowledge base. Provides architecture, DDD integration, persistence, DI, security, messenger, workflow, events, infrastructure components, testing, and antipatterns for Symfony PHP projects.
stability-patterns-knowledge
Stability Patterns knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Circuit Breaker, Retry, Rate Limiter, Bulkhead, and resilience audits.
solid-knowledge
SOLID principles knowledge base for PHP 8.4 projects. Provides quick reference for SRP, OCP, LSP, ISP, DIP with detection patterns, PHP examples, and antipattern identification. Use for architecture audits and code quality reviews.
scalability-knowledge
Scalability knowledge base. Provides vertical vs horizontal scaling, stateless design, session management, connection pooling, capacity planning, and PHP-FPM tuning for scalability audits.
saga-pattern-knowledge
Saga Pattern knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for saga orchestration, choreography, and distributed transaction audits.
psr-coding-style-knowledge
PSR-1 and PSR-12 coding standards knowledge base for PHP 8.4 projects. Provides quick reference for basic coding standard and extended coding style with detection patterns, examples, and antipattern identification. Use for code style audits and compliance reviews.
psr-autoloading-knowledge
PSR-4 autoloading standard knowledge base for PHP 8.4 projects. Provides quick reference for namespace-to-path mapping, composer.json configuration, directory structure, and common mistakes. Use for autoloading audits and project structure reviews.
outbox-pattern-knowledge
Outbox Pattern knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for transactional outbox, polling publisher, and reliable messaging audits.
observability-knowledge
Observability knowledge base. Provides three pillars (logs, metrics, traces), structured logging, distributed tracing, metrics collection (RED/USE), SLI/SLO/SLA definitions for observability audits and generation.