drizzle-team / drizzle-team/drizzle-orm

[BUG]: drizzle-kit push (pg): numeric index .with() params never match text reloptions — index dropped and rebuilt on every push

Open
#6,079 2 comments 0 reactions 0 assignees View on GitHub
bug bug/fixed-in-beta drizzle/kit
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

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

0.45.2

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

0.31.10

### Describe the Bug

Declaring Postgres index storage parameters (`.with()`) with **numeric** values makes `drizzle-kit push` DROP and re-CREATE that index on **every** push, forever:

```ts
index('chunk_embedding_hnsw_idx')
.using('hnsw', t.embedding.op('vector_cosine_ops'))
.with({ m: 24, ef_construction: 128 }),
```

Every push (no schema changes) emits:

```sql
DROP INDEX "chunk_embedding_hnsw_idx";
CREATE INDEX "chunk_embedding_hnsw_idx" ON "chunk" USING hnsw ("embedding" vector_cosine_ops) WITH (m=24,ef_construction=128);
```

Postgres reloptions introspect as text — the DB-side snapshot holds `{"m": "24", "ef_construction": "128"}` — while the schema side serializes numbers (`{"m": 24, ...}`), so the comparison never matches.

In practice this is dangerous, not just noisy: an HNSW rebuild over a few hundred thousand pgvector rows is many minutes of zero-output "hang" on every push, and interrupting the seemingly-frozen push leaves the database **without the index** (ours ran on seq scan until we noticed).

### Workaround

Declare the params as strings — `.with({ m: '24', ef_construction: '128' })` — the diff goes quiet immediately.

### Suggested fix

Normalize `with` values before comparing in the differ (stringify both sides, or coerce introspected reloptions to numbers). The type accepted by `.with()` could also be narrowed/documented to strings to make the footgun impossible.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with drizzle-kit push and a Postgres index using numeric .with() values, then inspect the differ's comparison between schema-side values and the database snapshot's text reloptions. Done means repeated pushes with no schema changes emit no DROP/CREATE for the index and leave the index intact.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.