@@ -27,6 +27,17 @@ import {
2727} from 'drizzle-orm/pg-core'
2828import { DEFAULT_FREE_CREDITS , TAG_SLOTS } from './constants'
2929
30+ /**
31+ * Drizzle push compares index options as JSON, while Postgres introspection
32+ * returns strings. Normalize only dev pushes so unchanged HNSW indexes survive
33+ * the diff; versioned migration snapshots retain their original numeric values.
34+ */
35+ function hnswIndexOptions ( ) {
36+ return process . env . SIM_DEV_DB_PUSH === '1'
37+ ? { m : '16' , ef_construction : '64' }
38+ : { m : 16 , ef_construction : 64 }
39+ }
40+
3041// Custom tsvector type for full-text search
3142export const tsvector = customType < {
3243 data : string
@@ -3194,28 +3205,16 @@ export const embedding = pgTable(
31943205 // Vector similarity search indexes (HNSW), one per stored width
31953206 embeddingVectorHnswIdx : index ( 'embedding_vector_hnsw_idx' )
31963207 . using ( 'hnsw' , table . embedding . op ( 'vector_cosine_ops' ) )
3197- . with ( {
3198- m : 16 ,
3199- ef_construction : 64 ,
3200- } ) ,
3208+ . with ( hnswIndexOptions ( ) ) ,
32013209 embedding384VectorHnswIdx : index ( 'embedding_384_vector_hnsw_idx' )
32023210 . using ( 'hnsw' , table . embedding384 . op ( 'vector_cosine_ops' ) )
3203- . with ( {
3204- m : 16 ,
3205- ef_construction : 64 ,
3206- } ) ,
3211+ . with ( hnswIndexOptions ( ) ) ,
32073212 embedding768VectorHnswIdx : index ( 'embedding_768_vector_hnsw_idx' )
32083213 . using ( 'hnsw' , table . embedding768 . op ( 'vector_cosine_ops' ) )
3209- . with ( {
3210- m : 16 ,
3211- ef_construction : 64 ,
3212- } ) ,
3214+ . with ( hnswIndexOptions ( ) ) ,
32133215 embedding1024VectorHnswIdx : index ( 'embedding_1024_vector_hnsw_idx' )
32143216 . using ( 'hnsw' , table . embedding1024 . op ( 'vector_cosine_ops' ) )
3215- . with ( {
3216- m : 16 ,
3217- ef_construction : 64 ,
3218- } ) ,
3217+ . with ( hnswIndexOptions ( ) ) ,
32193218 /**
32203219 * pgvector indexes `vector` only up to 2,000 dimensions and `halfvec` up to
32213220 * 4,000, so the 3,072 column is indexed through a `halfvec` cast — the
@@ -3236,27 +3235,24 @@ export const embedding = pgTable(
32363235 */
32373236 embedding3072VectorHnswIdx : index ( 'embedding_3072_vector_hnsw_idx' )
32383237 . using ( 'hnsw' , sql `(${ table . embedding3072 } ::halfvec(3072)) halfvec_cosine_ops` )
3239- . with ( {
3240- m : 16 ,
3241- ef_construction : 64 ,
3242- } ) ,
3238+ . with ( hnswIndexOptions ( ) ) ,
32433239
32443240 /** contract-pending(after stored candidate retrieval is fully deployed): remove these expression indexes; old app versions still query them during rollout. */
32453241 embeddingBinaryHnswIdx : index ( 'embedding_binary_hnsw_idx' )
32463242 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding } )::bit(1536)) bit_hamming_ops` )
3247- . with ( { m : 16 , ef_construction : 64 } ) ,
3243+ . with ( hnswIndexOptions ( ) ) ,
32483244 embedding384BinaryHnswIdx : index ( 'embedding_384_binary_hnsw_idx' )
32493245 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding384 } )::bit(384)) bit_hamming_ops` )
3250- . with ( { m : 16 , ef_construction : 64 } ) ,
3246+ . with ( hnswIndexOptions ( ) ) ,
32513247 embedding768BinaryHnswIdx : index ( 'embedding_768_binary_hnsw_idx' )
32523248 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding768 } )::bit(768)) bit_hamming_ops` )
3253- . with ( { m : 16 , ef_construction : 64 } ) ,
3249+ . with ( hnswIndexOptions ( ) ) ,
32543250 embedding1024BinaryHnswIdx : index ( 'embedding_1024_binary_hnsw_idx' )
32553251 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding1024 } )::bit(1024)) bit_hamming_ops` )
3256- . with ( { m : 16 , ef_construction : 64 } ) ,
3252+ . with ( hnswIndexOptions ( ) ) ,
32573253 embedding3072BinaryHnswIdx : index ( 'embedding_3072_binary_hnsw_idx' )
32583254 . using ( 'hnsw' , sql `(binary_quantize(${ table . embedding3072 } )::bit(3072)) bit_hamming_ops` )
3259- . with ( { m : 16 , ef_construction : 64 } ) ,
3255+ . with ( hnswIndexOptions ( ) ) ,
32603256
32613257 // Text tag indexes
32623258 tag1Idx : index ( 'emb_kb_tag1_lower_idx' ) . on ( table . knowledgeBaseId , sql `lower(${ table . tag1 } )` ) ,
@@ -3349,37 +3345,37 @@ export const embeddingSearch = pgTable(
33493345 . where ( sql `${ table . enabled } ` ) ,
33503346 binaryIdx : index ( 'embedding_search_binary_hnsw_idx' )
33513347 . using ( 'hnsw' , table . binary . op ( 'bit_hamming_ops' ) )
3352- . with ( { m : 16 , ef_construction : 64 } ) ,
3348+ . with ( hnswIndexOptions ( ) ) ,
33533349 binary384Idx : index ( 'embedding_search_384_binary_hnsw_idx' )
33543350 . using ( 'hnsw' , table . binary384 . op ( 'bit_hamming_ops' ) )
3355- . with ( { m : 16 , ef_construction : 64 } ) ,
3351+ . with ( hnswIndexOptions ( ) ) ,
33563352 binary768Idx : index ( 'embedding_search_768_binary_hnsw_idx' )
33573353 . using ( 'hnsw' , table . binary768 . op ( 'bit_hamming_ops' ) )
3358- . with ( { m : 16 , ef_construction : 64 } ) ,
3354+ . with ( hnswIndexOptions ( ) ) ,
33593355 binary1024Idx : index ( 'embedding_search_1024_binary_hnsw_idx' )
33603356 . using ( 'hnsw' , table . binary1024 . op ( 'bit_hamming_ops' ) )
3361- . with ( { m : 16 , ef_construction : 64 } ) ,
3357+ . with ( hnswIndexOptions ( ) ) ,
33623358 binary3072Idx : index ( 'embedding_search_3072_binary_hnsw_idx' )
33633359 . using ( 'hnsw' , table . binary3072 . op ( 'bit_hamming_ops' ) )
3364- . with ( { m : 16 , ef_construction : 64 } ) ,
3360+ . with ( hnswIndexOptions ( ) ) ,
33653361 vectorIdx : index ( 'embedding_search_cosine_hnsw_idx' )
33663362 . using ( 'hnsw' , table . vector . op ( 'halfvec_cosine_ops' ) )
3367- . with ( { m : 16 , ef_construction : 64 } ) ,
3363+ . with ( hnswIndexOptions ( ) ) ,
33683364 vector512Idx : index ( 'embedding_search_512_cosine_hnsw_idx' )
33693365 . using ( 'hnsw' , table . vector512 . op ( 'halfvec_cosine_ops' ) )
3370- . with ( { m : 16 , ef_construction : 64 } ) ,
3366+ . with ( hnswIndexOptions ( ) ) ,
33713367 vector384Idx : index ( 'embedding_search_384_cosine_hnsw_idx' )
33723368 . using ( 'hnsw' , table . vector384 . op ( 'halfvec_cosine_ops' ) )
3373- . with ( { m : 16 , ef_construction : 64 } ) ,
3369+ . with ( hnswIndexOptions ( ) ) ,
33743370 vector768Idx : index ( 'embedding_search_768_cosine_hnsw_idx' )
33753371 . using ( 'hnsw' , table . vector768 . op ( 'halfvec_cosine_ops' ) )
3376- . with ( { m : 16 , ef_construction : 64 } ) ,
3372+ . with ( hnswIndexOptions ( ) ) ,
33773373 vector1024Idx : index ( 'embedding_search_1024_cosine_hnsw_idx' )
33783374 . using ( 'hnsw' , table . vector1024 . op ( 'halfvec_cosine_ops' ) )
3379- . with ( { m : 16 , ef_construction : 64 } ) ,
3375+ . with ( hnswIndexOptions ( ) ) ,
33803376 vector3072Idx : index ( 'embedding_search_3072_cosine_hnsw_idx' )
33813377 . using ( 'hnsw' , table . vector3072 . op ( 'halfvec_cosine_ops' ) )
3382- . with ( { m : 16 , ef_construction : 64 } ) ,
3378+ . with ( hnswIndexOptions ( ) ) ,
33833379 widthCheck : check (
33843380 'embedding_search_width_check' ,
33853381 sql `num_nonnulls("binary", "binary_384", "binary_768", "binary_1024", "binary_3072") = 1`
@@ -3456,10 +3452,7 @@ export const docsEmbeddings = pgTable(
34563452 // Vector similarity search indexes (HNSW) - optimized for documentation embeddings
34573453 embeddingVectorHnswIdx : index ( 'docs_embedding_vector_hnsw_idx' )
34583454 . using ( 'hnsw' , table . embedding . op ( 'vector_cosine_ops' ) )
3459- . with ( {
3460- m : 16 ,
3461- ef_construction : 64 ,
3462- } ) ,
3455+ . with ( hnswIndexOptions ( ) ) ,
34633456
34643457 // GIN index for JSONB metadata queries
34653458 metadataGinIdx : index ( 'docs_emb_metadata_gin_idx' ) . using ( 'gin' , table . metadata ) ,
0 commit comments