drizzle-team / drizzle-team/drizzle-orm

[BUG]: withReplicas sends reads to a replica inside an Effect transaction

Open
#6,234 4 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### Report hasn't been filed before.

- [x] I have verified that the bug I'm about to report hasn't been filed before.

### What version of `drizzle-orm` are you using?

1.0.0-rc.5-ab785fc

### What version of `drizzle-kit` are you using?

1.0.0-rc.5-ab785fc

### Other packages

Not maintained by Drizzle: @effect/sql-pg@4.0.0-rc.112, effect@4.0.0-rc.112

### Describe the Bug

With the Effect driver, transactions are context-based: everything executed through the same `PgClient` inside `db.transaction` joins it. `withReplicas` ignores that and keeps routing `select` / `with` / `$count` / `query` to a replica, so reads inside a transaction go to another client, outside the transaction.

```ts
const db = withReplicas(primary, [replica]) // two PgClient pools on the same server

yield* db.transaction(() =>
Effect.gen(function* () {
yield* db.insert(items).values({ value: 'pending' })
return yield* db.select().from(items).where(eq(items.value, 'pending'))
})
)
// -> [] : the select ran on the replica connection, the insert is not committed yet
```

Asserting `current_setting('application_name')` in the select shows the replica pool. The promise driver doesn't have this problem since reads inside a transaction go through `tx` (`db.transaction((tx => {})`). With the Effect driver the whole point is that nested code keep using `db` and joins the ambient transaction, which works for writes but not for reads.

Expected: reads routed to the primary while it has a transaction open. The transaction is in the fiber context (`primary.$client.transactionService`), so `withReplicas` could check it at execution time.

Kinda related, accidentally one of my old issues: #4185

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the example with withReplicas, db.transaction, and the Effect driver, then trace withReplicas alongside primary.$client.transactionService. Verify the behavior using the reported current_setting('application_name') check: reads such as select, with, $count, and query should use the primary while the transaction is open.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, typescript
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.