---
title: Use Read/Write Replica Separation
impact: HIGH
impactDescription: Reduces primary DB load and improves read performance
tags: data, prisma, replicas, performance, postgresql
---
## Паспорт документа

- Статус документа: living standard
- Актуально на: 28 марта 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении инженерной практики, CI/CD, архитектурных правил или локального workflow
- Область применения: внутренние rule/reference-card документы для инженерной команды
- Связанные документы:
  - [Индекс Agents](../README.md)
  - [Команды разработки](../commands.md)
  - [Инженерные принципы](../../governance/engineering-principles.md)

## Use Read/Write Replica Separation

**Impact: HIGH**

All read operations (SELECT) must use the read replica. Only write operations (INSERT, UPDATE, DELETE) use the primary database connection.

**Implementation with Prisma:**

```typescript
// prisma/prisma.service.ts
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
  private replicaClient: PrismaClient | null = null;

  constructor() {
    super({ datasourceUrl: process.env.DATABASE_URL });

    if (process.env.DATABASE_REPLICA_URL) {
      this.replicaClient = new PrismaClient({
        datasourceUrl: process.env.DATABASE_REPLICA_URL,
      });
    }
  }

  $replica() {
    return this.replicaClient || this;
  }

  async onModuleInit() {
    await this.$connect();
    if (this.replicaClient) await this.replicaClient.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
    if (this.replicaClient) await this.replicaClient.$disconnect();
  }
}
```

**Usage in repositories:**

```typescript
@Injectable()
export class CatalogRepository {
  constructor(private readonly prisma: PrismaService) {}

  // READ — use replica
  async findPublished(filters: CatalogFilters) {
    return this.prisma.$replica().item.findMany({
      where: this.buildWhereClause(filters),
      select: { id: true, name: true, slug: true, priceFrom: true },
    });
  }

  // WRITE — use primary
  async create(data: CreateItemDTO) {
    return this.prisma.item.create({ data });
  }

  // WRITE — use primary
  async updateStatus(id: string, status: ItemStatus) {
    return this.prisma.item.update({
      where: { id },
      data: { status },
    });
  }
}
```

**Rules:**
- `$replica()` for all `findMany`, `findFirst`, `findUnique`, `count`, `aggregate`
- Default `this.prisma` (primary) for all `create`, `update`, `delete`, `upsert`
- In development with no replica configured, `$replica()` falls back to primary
