Skip to content

feat: add read-replica routing and query load-balancing - #120

Merged
Miracle656 merged 1 commit into
Miracle656:mainfrom
mallison031:feat/118-read-replica-routing
Jun 24, 2026
Merged

feat: add read-replica routing and query load-balancing#120
Miracle656 merged 1 commit into
Miracle656:mainfrom
mallison031:feat/118-read-replica-routing

Conversation

@mallison031

@mallison031 mallison031 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Closes #123

Adds a routing layer to src/db.ts that automatically routes read-heavy

traffic to replicas while sending all writes to the primary database,
improving throughput and isolating ingest contention.

### What Changed
- Created `src/db/router.ts` with a `withReadReplicas` Prisma Client

Extension.
- Reads (findMany, findUnique, count, etc.) and raw queries
($queryRaw) are now round-robined across DATABASE_REPLICAS.
- Updated src/db.ts to wrap the exported prisma singleton in the
router.
- Added comprehensive unit tests for the router in
src/db/__tests__/router.test.ts.

### Key Design Decisions
- **Read-Your-Writes:** Leveraged Prisma extensions' native context to

check if a query is executing inside a $transaction. Interactive
transactions bypass replicas and route strictly to the primary, cleanly
preserving read-your-writes guarantees for all grouped operations in the
repo.
- Health Checks & Failover: A background loop continuously pings
replicas via SELECT 1. If a replica fails a ping—or if a query fails mid-
flight—it's marked unhealthy, temporarily removed from the round-robin, and
traffic gracefully falls back to the primary.

### Acceptance Criteria
- [x] Reads load-balanced across healthy replicas
- [x] Unhealthy replica removed; traffic fails over to primary
- [x] Tests for routing and failover
- [x] Respects read-your-writes (automatically routes all `$transaction`

queries to primary)

### Test & Coverage
- Tests pass locally.
- Router logic achieves `100%` function and `97%` line coverage.

### Security Note
Replicas are passed via the standard environment configuration

(DATABASE_REPLICAS). Connection logic avoids exposing URI components or
logging credentials.

Closes #118

@Miracle656 Miracle656 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid implementation of read-replica routing (#118). withReadReplicas uses a Prisma $extends query interceptor to send reads to round-robined healthy replicas while writes and anything inside a transaction go to the primary; the background health-check loop marks replicas unhealthy and fails over to primary, and interval.unref() keeps the process exitable. It's wired in cleanly via DATABASE_REPLICAS with a zero-config passthrough default (no replicas → primary unchanged), and the tests cover read/write routing, transaction bypass, round-robin, and unhealthy fallback. Merging — nice work!

@Miracle656
Miracle656 merged commit 02bb92c into Miracle656:main Jun 24, 2026
1 check passed
@drips-wave

drips-wave Bot commented Jun 24, 2026

Copy link
Copy Markdown

@mallison031 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read-replica routing & query load-balancing

2 participants