@@ -28,6 +28,17 @@ import {
2828} from 'drizzle-orm/pg-core'
2929import { DEFAULT_FREE_CREDITS , TAG_SLOTS } from './constants'
3030
31+ /**
32+ * Drizzle push compares index options as JSON, while Postgres introspection
33+ * returns strings. Normalize only dev pushes so unchanged HNSW indexes survive
34+ * the diff; versioned migration snapshots retain their original numeric values.
35+ */
36+ function hnswIndexOptions ( ) {
37+ return process . env . SIM_DEV_DB_PUSH === '1'
38+ ? { m : '16' , ef_construction : '64' }
39+ : { m : 16 , ef_construction : 64 }
40+ }
41+
3142// Custom tsvector type for full-text search
3243export const tsvector = customType < {
3344 data : string
@@ -3236,28 +3247,16 @@ export const embedding = pgTable(
32363247 // Vector similarity search indexes (HNSW), one per stored width
32373248 embeddingVectorHnswIdx : index ( 'embedding_vector_hnsw_idx' )
32383249 . using ( 'hnsw' , table . embedding . op ( 'vector_cosine_ops' ) )
3239- . with ( {
3240- m : 16 ,
3241- ef_construction : 64 ,
3242- } ) ,
3250+ . with ( hnswIndexOptions ( ) ) ,
32433251 embedding384VectorHnswIdx : index ( 'embedding_384_vector_hnsw_idx' )
32443252 . using ( 'hnsw' , table . embedding384 . op ( 'vector_cosine_ops' ) )
3245- . with ( {
3246- m : 16 ,
3247- ef_construction : 64 ,
3248- } ) ,
3253+ . with ( hnswIndexOptions ( ) ) ,
32493254 embedding768VectorHnswIdx : index ( 'embedding_768_vector_hnsw_idx' )
32503255 . using ( 'hnsw' , table . embedding768 . op ( 'vector_cosine_ops' ) )
3251- . with ( {
3252- m : 16 ,
3253- ef_construction : 64 ,
3254- } ) ,
3256+ . with ( hnswIndexOptions ( ) ) ,
32553257 embedding1024VectorHnswIdx : index ( 'embedding_1024_vector_hnsw_idx' )
32563258 . using ( 'hnsw' , table . embedding1024 . op ( 'vector_cosine_ops' ) )
3257- . with ( {
3258- m : 16 ,
3259- ef_construction : 64 ,
3260- } ) ,
3259+ . with ( hnswIndexOptions ( ) ) ,
32613260 /**
32623261 * pgvector indexes `vector` only up to 2,000 dimensions and `halfvec` up to
32633262 * 4,000, so the 3,072 column is indexed through a `halfvec` cast — the
@@ -3278,27 +3277,24 @@ export const embedding = pgTable(
32783277 */
32793278 embedding3072VectorHnswIdx : index ( 'embedding_3072_vector_hnsw_idx' )
32803279 . using ( 'hnsw' , sql `(${ table . embedding3072 } ::halfvec(3072)) halfvec_cosine_ops` )
3281- . with ( {
3282- m : 16 ,
3283- ef_construction : 64 ,
3284- } ) ,
3280+ . with ( hnswIndexOptions ( ) ) ,
32853281
32863282 /** contract-pending(after stored candidate retrieval is fully deployed): remove these expression indexes; old app versions still query them during rollout. */
32873283 embeddingBinaryHnswIdx : index ( 'embedding_binary_hnsw_idx' )
32883284 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding } )::bit(1536)) bit_hamming_ops` )
3289- . with ( { m : 16 , ef_construction : 64 } ) ,
3285+ . with ( hnswIndexOptions ( ) ) ,
32903286 embedding384BinaryHnswIdx : index ( 'embedding_384_binary_hnsw_idx' )
32913287 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding384 } )::bit(384)) bit_hamming_ops` )
3292- . with ( { m : 16 , ef_construction : 64 } ) ,
3288+ . with ( hnswIndexOptions ( ) ) ,
32933289 embedding768BinaryHnswIdx : index ( 'embedding_768_binary_hnsw_idx' )
32943290 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding768 } )::bit(768)) bit_hamming_ops` )
3295- . with ( { m : 16 , ef_construction : 64 } ) ,
3291+ . with ( hnswIndexOptions ( ) ) ,
32963292 embedding1024BinaryHnswIdx : index ( 'embedding_1024_binary_hnsw_idx' )
32973293 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding1024 } )::bit(1024)) bit_hamming_ops` )
3298- . with ( { m : 16 , ef_construction : 64 } ) ,
3294+ . with ( hnswIndexOptions ( ) ) ,
32993295 embedding3072BinaryHnswIdx : index ( 'embedding_3072_binary_hnsw_idx' )
33003296 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding3072 } )::bit(3072)) bit_hamming_ops` )
3301- . with ( { m : 16 , ef_construction : 64 } ) ,
3297+ . with ( hnswIndexOptions ( ) ) ,
33023298
33033299 // Text tag indexes
33043300 tag1Idx : index ( 'emb_kb_tag1_lower_idx' ) . on ( table . knowledgeBaseId , sql `lower(${ table . tag1 } )` ) ,
@@ -3387,37 +3383,37 @@ export const embeddingSearch = pgTable(
33873383 knowledgeBaseIdx : index ( 'embedding_search_kb_idx' ) . on ( table . knowledgeBaseId ) ,
33883384 binaryIdx : index ( 'embedding_search_binary_hnsw_idx' )
33893385 . using ( 'hnsw' , table . binary . op ( 'bit_hamming_ops' ) )
3390- . with ( { m : 16 , ef_construction : 64 } ) ,
3386+ . with ( hnswIndexOptions ( ) ) ,
33913387 binary384Idx : index ( 'embedding_search_384_binary_hnsw_idx' )
33923388 . using ( 'hnsw' , table . binary384 . op ( 'bit_hamming_ops' ) )
3393- . with ( { m : 16 , ef_construction : 64 } ) ,
3389+ . with ( hnswIndexOptions ( ) ) ,
33943390 binary768Idx : index ( 'embedding_search_768_binary_hnsw_idx' )
33953391 . using ( 'hnsw' , table . binary768 . op ( 'bit_hamming_ops' ) )
3396- . with ( { m : 16 , ef_construction : 64 } ) ,
3392+ . with ( hnswIndexOptions ( ) ) ,
33973393 binary1024Idx : index ( 'embedding_search_1024_binary_hnsw_idx' )
33983394 . using ( 'hnsw' , table . binary1024 . op ( 'bit_hamming_ops' ) )
3399- . with ( { m : 16 , ef_construction : 64 } ) ,
3395+ . with ( hnswIndexOptions ( ) ) ,
34003396 binary3072Idx : index ( 'embedding_search_3072_binary_hnsw_idx' )
34013397 . using ( 'hnsw' , table . binary3072 . op ( 'bit_hamming_ops' ) )
3402- . with ( { m : 16 , ef_construction : 64 } ) ,
3398+ . with ( hnswIndexOptions ( ) ) ,
34033399 vectorIdx : index ( 'embedding_search_cosine_hnsw_idx' )
34043400 . using ( 'hnsw' , table . vector . op ( 'halfvec_cosine_ops' ) )
3405- . with ( { m : 16 , ef_construction : 64 } ) ,
3401+ . with ( hnswIndexOptions ( ) ) ,
34063402 vector512Idx : index ( 'embedding_search_512_cosine_hnsw_idx' )
34073403 . using ( 'hnsw' , table . vector512 . op ( 'halfvec_cosine_ops' ) )
3408- . with ( { m : 16 , ef_construction : 64 } ) ,
3404+ . with ( hnswIndexOptions ( ) ) ,
34093405 vector384Idx : index ( 'embedding_search_384_cosine_hnsw_idx' )
34103406 . using ( 'hnsw' , table . vector384 . op ( 'halfvec_cosine_ops' ) )
3411- . with ( { m : 16 , ef_construction : 64 } ) ,
3407+ . with ( hnswIndexOptions ( ) ) ,
34123408 vector768Idx : index ( 'embedding_search_768_cosine_hnsw_idx' )
34133409 . using ( 'hnsw' , table . vector768 . op ( 'halfvec_cosine_ops' ) )
3414- . with ( { m : 16 , ef_construction : 64 } ) ,
3410+ . with ( hnswIndexOptions ( ) ) ,
34153411 vector1024Idx : index ( 'embedding_search_1024_cosine_hnsw_idx' )
34163412 . using ( 'hnsw' , table . vector1024 . op ( 'halfvec_cosine_ops' ) )
3417- . with ( { m : 16 , ef_construction : 64 } ) ,
3413+ . with ( hnswIndexOptions ( ) ) ,
34183414 vector3072Idx : index ( 'embedding_search_3072_cosine_hnsw_idx' )
34193415 . using ( 'hnsw' , table . vector3072 . op ( 'halfvec_cosine_ops' ) )
3420- . with ( { m : 16 , ef_construction : 64 } ) ,
3416+ . with ( hnswIndexOptions ( ) ) ,
34213417 widthCheck : check (
34223418 'embedding_search_width_check' ,
34233419 sql `num_nonnulls("binary", "binary_384", "binary_768", "binary_1024", "binary_3072") = 1`
@@ -3494,10 +3490,7 @@ export const docsEmbeddings = pgTable(
34943490 // Vector similarity search indexes (HNSW) - optimized for documentation embeddings
34953491 embeddingVectorHnswIdx : index ( 'docs_embedding_vector_hnsw_idx' )
34963492 . using ( 'hnsw' , table . embedding . op ( 'vector_cosine_ops' ) )
3497- . with ( {
3498- m : 16 ,
3499- ef_construction : 64 ,
3500- } ) ,
3493+ . with ( hnswIndexOptions ( ) ) ,
35013494
35023495 // GIN index for JSONB metadata queries
35033496 metadataGinIdx : index ( 'docs_emb_metadata_gin_idx' ) . using ( 'gin' , table . metadata ) ,
0 commit comments