проектdocs/Agents/rules/data-read-write-replicas.md
data-read-write-replicas.md
Обновлён 1 апр. 2026 г., 12:41 · 0 комментариев
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 документы для инженерной команды
- Связанные документы:
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:
// 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:
@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 allfindMany,findFirst,findUnique,count,aggregate- Default
this.prisma(primary) for allcreate,update,delete,upsert - In development with no replica configured,
$replica()falls back to primary