1:"$Sreact.fragment"
2:I[15579,["/_next/static/chunks/fd0661f1506dcbc6.js","/_next/static/chunks/94245cbda44972fe.js","/_next/static/chunks/af778fff4a0f4be6.js","/_next/static/chunks/b096b037d08e2f31.js"],"Navigation"]
3:I[3013,["/_next/static/chunks/fd0661f1506dcbc6.js","/_next/static/chunks/94245cbda44972fe.js","/_next/static/chunks/af778fff4a0f4be6.js","/_next/static/chunks/b096b037d08e2f31.js"],""]
58:I[41451,["/_next/static/chunks/fd0661f1506dcbc6.js","/_next/static/chunks/94245cbda44972fe.js","/_next/static/chunks/af778fff4a0f4be6.js","/_next/static/chunks/b096b037d08e2f31.js"],"Footer"]
59:I[47913,["/_next/static/chunks/316a3a63422f35de.js"],"OutletBoundary"]
5a:"$Sreact.suspense"
:HL["/blog/posts/postgres-sequence-race-condition/hero.jpg","image"]
:HL["/blog/posts/logo.png","image"]
0:{"buildId":"TlpKRvbES4zzM7LeczAM7","rsc":["$","$1","c",{"children":[[["$","$L2",null,{}],["$","main",null,{"className":"pt-20 md:pt-24","children":["$","article",null,{"children":[["$","header",null,{"className":"border-b border-border","children":["$","div",null,{"className":"container mx-auto px-6 py-14 md:py-20","children":[["$","$L3",null,{"href":"/blog","className":"mb-8 inline-flex items-center text-sm font-medium text-muted-foreground transition-colors hover:text-foreground","children":[["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":24,"height":24,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-arrow-left mr-2 h-4 w-4","aria-hidden":"true","children":[["$","path","1l729n",{"d":"m12 19-7-7 7-7"}],["$","path","x3x0zl",{"d":"M19 12H5"}],"$undefined"]}],"Blog"]}],["$","div",null,{"className":"grid gap-8 md:grid-cols-[1fr_0.9fr] md:items-start","children":[["$","div",null,{"className":"max-w-3xl","children":[["$","div",null,{"className":"mb-5 flex flex-wrap items-center gap-3 text-sm text-muted-foreground","children":[["$","span",null,{"className":"rounded-md border border-primary/40 bg-primary/10 px-2.5 py-1 text-primary","children":"Database"}],["$","span",null,{"children":"2026-W20"}],["$","span",null,{"aria-hidden":"true","children":"/"}],["$","span",null,{"children":"5 min read"}],[["$","span",null,{"aria-hidden":"true","children":"/"}],["$","span",null,{"children":["by ",["$","span",null,{"className":"font-medium text-foreground","children":"delve"}]]}]]]}],["$","h1",null,{"className":"text-4xl font-bold leading-tight text-balance md:text-6xl","children":"The Select-Then-Insert Race Condition in Version Counters"}],["$","p",null,{"className":"mt-6 text-lg leading-relaxed text-muted-foreground md:text-xl","children":"A `SELECT MAX()+1` then `INSERT` pattern looks correct in development and fails silently under any real concurrency. The fix lives in the database, not the application."}]]}],["$","div",null,{"className":"overflow-hidden rounded-lg border border-border bg-card","children":["$","div",null,{"className":"relative aspect-[16/9] overflow-hidden","children":[null,["$","img",null,{"src":"/blog/posts/postgres-sequence-race-condition/hero.jpg","alt":"Two runners' shoes captured mid-stride at the exact same finish line, viewed straight down from above.","className":"h-full w-full object-cover"}],["$","img",null,{"src":"/blog/posts/logo.png","alt":"","aria-hidden":"true","className":"pointer-events-none absolute right-4 top-4 h-[50px] w-[50px] mix-blend-screen"}]]}]}]]}]]}]}],["$","div",null,{"className":"container mx-auto px-6 py-12 md:py-16","children":["$","div",null,{"className":"grid gap-10 lg:grid-cols-[minmax(0,1fr)_280px] lg:items-start","children":[["$","div",null,{"className":"max-w-3xl text-muted-foreground","children":[[["$","h2","h2-0",{"className":"mt-12 text-2xl font-semibold leading-snug text-foreground first:mt-0","children":"The problem"}],"\n",["$","p","p-0",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"You need a monotonically increasing version counter on a table — an event offset, a row version for incremental sync, an instruction cursor. The naive implementation writes itself quickly:"}],"\n",["$","div","pre-0",{"style":{"background":"hsl(220, 13%, 18%)","color":"hsl(220, 14%, 71%)","textShadow":"0 1px rgba(0, 0, 0, 0.3)","fontFamily":"\"Fira Code\", \"Fira Mono\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace","direction":"ltr","textAlign":"left","whiteSpace":"pre","wordSpacing":"normal","wordBreak":"normal","lineHeight":"1.5","MozTabSize":"2","OTabSize":"2","tabSize":"2","WebkitHyphens":"none","MozHyphens":"none","msHyphens":"none","hyphens":"none","padding":"1rem","margin":"0.5em 0","overflow":"auto","borderRadius":"0.5rem","marginTop":"1.25rem","marginBottom":0,"border":"1px solid hsl(var(--border))","fontSize":"0.875rem"},"children":["$","code",null,{"style":{"whiteSpace":"pre","fontFamily":"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace"},"children":[false,["$L4","$L5","$L6","$L7","$L8","$L9","$La","$Lb","$Lc","$Ld","$Le","$Lf","$L10","$L11","$L12","$L13","$L14","$L15","$L16","$L17","$L18","$L19","$L1a","$L1b","$L1c","$L1d","$L1e","$L1f","$L20","$L21","$L22","$L23","$L24","$L25","$L26","$L27","$L28","$L29","$L2a","$L2b","$L2c","$L2d","$L2e","$L2f","$L30","$L31","$L32","$L33","$L34","$L35","$L36","$L37","$L38","$L39","$L3a","$L3b","$L3c"]]}]}],"\n","$L3d","\n","$L3e","\n","$L3f","\n","$L40","\n","$L41","\n","$L42","\n","$L43","\n","$L44","\n","$L45","\n","$L46","\n","$L47","\n","$L48","\n","$L49","\n","$L4a","\n","$L4b","\n","$L4c","\n","$L4d","\n","$L4e","\n","$L4f","\n","$L50"],"$L51",null]}],"$L52"]}]}]]}]}],"$L53"],["$L54","$L55","$L56"],"$L57"]}],"loading":null,"isPartial":false}
4:["$","span","code-segment-0",{"className":"token","style":{"color":"hsl(220, 10%, 40%)","fontStyle":"italic"},"children":["# Get the current max, add 1, use that as the next version"]}]
5:["$","span","code-segment-1",{"style":{},"children":["\n"]}]
6:["$","span","code-segment-2",{"style":{},"children":["result "]}]
7:["$","span","code-segment-3",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}]
8:["$","span","code-segment-4",{"style":{},"children":[" db"]}]
9:["$","span","code-segment-5",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
a:["$","span","code-segment-6",{"style":{},"children":["execute"]}]
b:["$","span","code-segment-7",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}]
c:["$","span","code-segment-8",{"style":{},"children":["\n"]}]
d:["$","span","code-segment-9",{"style":{},"children":["    "]}]
e:["$","span","code-segment-10",{"className":"token","style":{"color":"hsl(95, 38%, 62%)"},"children":["\"SELECT COALESCE(MAX(version), 0) + 1 FROM events WHERE tenant = :t\""]}]
f:["$","span","code-segment-11",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[","]}]
10:["$","span","code-segment-12",{"style":{},"children":["\n"]}]
11:["$","span","code-segment-13",{"style":{},"children":["    "]}]
12:["$","span","code-segment-14",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["{"]}]
13:["$","span","code-segment-15",{"className":"token","style":{"color":"hsl(95, 38%, 62%)"},"children":["\"t\""]}]
14:["$","span","code-segment-16",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[":"]}]
15:["$","span","code-segment-17",{"style":{},"children":[" tenant"]}]
16:["$","span","code-segment-18",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["}"]}]
17:["$","span","code-segment-19",{"style":{},"children":["\n"]}]
18:["$","span","code-segment-20",{"style":{},"children":[""]}]
19:["$","span","code-segment-21",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]
1a:["$","span","code-segment-22",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
1b:["$","span","code-segment-23",{"style":{},"children":["scalar"]}]
1c:["$","span","code-segment-24",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}]
1d:["$","span","code-segment-25",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]
1e:["$","span","code-segment-26",{"style":{},"children":["\n"]}]
1f:["$","span","code-segment-27",{"style":{},"children":["new_event "]}]
20:["$","span","code-segment-28",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}]
21:["$","span","code-segment-29",{"style":{},"children":[" Event"]}]
22:["$","span","code-segment-30",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}]
23:["$","span","code-segment-31",{"style":{},"children":["tenant"]}]
24:["$","span","code-segment-32",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}]
25:["$","span","code-segment-33",{"style":{},"children":["tenant"]}]
26:["$","span","code-segment-34",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[","]}]
27:["$","span","code-segment-35",{"style":{},"children":[" version"]}]
28:["$","span","code-segment-36",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}]
29:["$","span","code-segment-37",{"style":{},"children":["result"]}]
2a:["$","span","code-segment-38",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[","]}]
2b:["$","span","code-segment-39",{"style":{},"children":[" "]}]
2c:["$","span","code-segment-40",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
2d:["$","span","code-segment-41",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
2e:["$","span","code-segment-42",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
2f:["$","span","code-segment-43",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]
30:["$","span","code-segment-44",{"style":{},"children":["\n"]}]
31:["$","span","code-segment-45",{"style":{},"children":["db"]}]
32:["$","span","code-segment-46",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
33:["$","span","code-segment-47",{"style":{},"children":["add"]}]
34:["$","span","code-segment-48",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}]
35:["$","span","code-segment-49",{"style":{},"children":["new_event"]}]
36:["$","span","code-segment-50",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]
37:["$","span","code-segment-51",{"style":{},"children":["\n"]}]
38:["$","span","code-segment-52",{"style":{},"children":["db"]}]
39:["$","span","code-segment-53",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}]
3a:["$","span","code-segment-54",{"style":{},"children":["commit"]}]
3b:["$","span","code-segment-55",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}]
3c:["$","span","code-segment-56",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]
3d:["$","p","p-1",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"Two reads, one write. Looks fine in development. Fails in production under any concurrency."}]
3e:["$","h2","h2-1",{"className":"mt-12 text-2xl font-semibold leading-snug text-foreground first:mt-0","children":"Why the naive approach fails"}]
3f:["$","p","p-2",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"The SELECT and the INSERT are two separate statements with no locking between them. Under concurrent load:"}]
40:["$","ol","ol-0",{"children":["\n",["$","li","li-0",{"children":["Request A reads ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"MAX(version) = 5"}],", computes ",["$","code","code-1",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"6"}]]}],"\n",["$","li","li-1",{"children":["Request B reads ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"MAX(version) = 5"}]," before A commits, also computes ",["$","code","code-1",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"6"}]]}],"\n",["$","li","li-2",{"children":["Both insert with ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"version = 6"}]]}],"\n"]}]
41:["$","p","p-3",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["You now have a duplicate version. Any consumer polling ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"WHERE version > :cursor"}]," will see one of the two rows, silently miss the other, and advance its cursor past both. Rows disappear from the feed with no error."]}]
42:["$","p","p-4",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"The window is small in local testing and grows under any real concurrency. A gunicorn worker with 4 processes hits this on the second concurrent request."}]
43:["$","p","p-5",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["Making this worse: adding a unique constraint on ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"version"}]," turns the silent data loss into an intermittent 500 — harder to debug, same root cause."]}]
44:["$","h2","h2-2",{"className":"mt-12 text-2xl font-semibold leading-snug text-foreground first:mt-0","children":"The fix"}]
45:["$","p","p-6",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"Move version assignment entirely to the database. Postgres sequences are designed for exactly this:"}]
46:["$","div","pre-1",{"style":{"background":"hsl(220, 13%, 18%)","color":"hsl(220, 14%, 71%)","textShadow":"0 1px rgba(0, 0, 0, 0.3)","fontFamily":"\"Fira Code\", \"Fira Mono\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace","direction":"ltr","textAlign":"left","whiteSpace":"pre","wordSpacing":"normal","wordBreak":"normal","lineHeight":"1.5","MozTabSize":"2","OTabSize":"2","tabSize":"2","WebkitHyphens":"none","MozHyphens":"none","msHyphens":"none","hyphens":"none","padding":"1rem","margin":"0.5em 0","overflow":"auto","borderRadius":"0.5rem","marginTop":"1.25rem","marginBottom":0,"border":"1px solid hsl(var(--border))","fontSize":"0.875rem"},"children":["$","code",null,{"style":{"whiteSpace":"pre","fontFamily":"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace"},"children":[false,[["$","span","code-segment-0",{"className":"token","style":{"color":"hsl(220, 10%, 40%)","fontStyle":"italic"},"children":["-- Run once at startup (idempotent)"]}],["$","span","code-segment-1",{"style":{},"children":["\n"]}],["$","span","code-segment-2",{"style":{},"children":[""]}],["$","span","code-segment-3",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["CREATE"]}],["$","span","code-segment-4",{"style":{},"children":[" SEQUENCE "]}],["$","span","code-segment-5",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["IF"]}],["$","span","code-segment-6",{"style":{},"children":[" "]}],["$","span","code-segment-7",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["NOT"]}],["$","span","code-segment-8",{"style":{},"children":[" "]}],["$","span","code-segment-9",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["EXISTS"]}],["$","span","code-segment-10",{"style":{},"children":[" event_version_seq"]}],["$","span","code-segment-11",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[";"]}],["$","span","code-segment-12",{"style":{},"children":["\n"]}],["$","span","code-segment-13",{"style":{},"children":[""]}],["$","span","code-segment-14",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["ALTER"]}],["$","span","code-segment-15",{"style":{},"children":[" "]}],["$","span","code-segment-16",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["TABLE"]}],["$","span","code-segment-17",{"style":{},"children":[" events\n"]}],["$","span","code-segment-18",{"style":{},"children":["  "]}],["$","span","code-segment-19",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["ADD"]}],["$","span","code-segment-20",{"style":{},"children":[" "]}],["$","span","code-segment-21",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["COLUMN"]}],["$","span","code-segment-22",{"style":{},"children":[" "]}],["$","span","code-segment-23",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["IF"]}],["$","span","code-segment-24",{"style":{},"children":[" "]}],["$","span","code-segment-25",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["NOT"]}],["$","span","code-segment-26",{"style":{},"children":[" "]}],["$","span","code-segment-27",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["EXISTS"]}],["$","span","code-segment-28",{"style":{},"children":[" version "]}],["$","span","code-segment-29",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["BIGINT"]}],["$","span","code-segment-30",{"style":{},"children":[" "]}],["$","span","code-segment-31",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["DEFAULT"]}],["$","span","code-segment-32",{"style":{},"children":[" nextval"]}],["$","span","code-segment-33",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}],["$","span","code-segment-34",{"className":"token","style":{"color":"hsl(95, 38%, 62%)"},"children":["'event_version_seq'"]}],["$","span","code-segment-35",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}],["$","span","code-segment-36",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[";"]}]]]}]}]
47:["$","p","p-7",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["With ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"DEFAULT nextval(...)"}],", every ",["$","code","code-1",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"INSERT"}]," statement that omits the ",["$","code","code-2",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"version"}]," column gets a unique, monotonically increasing value assigned atomically by Postgres. The Python application layer never reads the current max and never races."]}]
48:["$","p","p-8",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"The SQLAlchemy model needs no changes beyond declaring the column as nullable:"}]
49:["$","div","pre-2",{"style":{"background":"hsl(220, 13%, 18%)","color":"hsl(220, 14%, 71%)","textShadow":"0 1px rgba(0, 0, 0, 0.3)","fontFamily":"\"Fira Code\", \"Fira Mono\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace","direction":"ltr","textAlign":"left","whiteSpace":"pre","wordSpacing":"normal","wordBreak":"normal","lineHeight":"1.5","MozTabSize":"2","OTabSize":"2","tabSize":"2","WebkitHyphens":"none","MozHyphens":"none","msHyphens":"none","hyphens":"none","padding":"1rem","margin":"0.5em 0","overflow":"auto","borderRadius":"0.5rem","marginTop":"1.25rem","marginBottom":0,"border":"1px solid hsl(var(--border))","fontSize":"0.875rem"},"children":["$","code",null,{"style":{"whiteSpace":"pre","fontFamily":"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace"},"children":[false,[["$","span","code-segment-0",{"style":{},"children":["version "]}],["$","span","code-segment-1",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}],["$","span","code-segment-2",{"style":{},"children":[" Column"]}],["$","span","code-segment-3",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}],["$","span","code-segment-4",{"style":{},"children":["BigInteger"]}],["$","span","code-segment-5",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[","]}],["$","span","code-segment-6",{"style":{},"children":[" nullable"]}],["$","span","code-segment-7",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}],["$","span","code-segment-8",{"className":"token","style":{"color":"hsl(29, 54%, 61%)"},"children":["True"]}],["$","span","code-segment-9",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]]]}]}]
4a:["$","p","p-9",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["Existing rows keep ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"NULL"}]," (the sequence was not backfilled, which is correct — there is no meaningful order for pre-migration rows). Incremental poll consumers exclude NULL-versioned rows explicitly:"]}]
4b:["$","div","pre-3",{"style":{"background":"hsl(220, 13%, 18%)","color":"hsl(220, 14%, 71%)","textShadow":"0 1px rgba(0, 0, 0, 0.3)","fontFamily":"\"Fira Code\", \"Fira Mono\", Menlo, Consolas, \"DejaVu Sans Mono\", monospace","direction":"ltr","textAlign":"left","whiteSpace":"pre","wordSpacing":"normal","wordBreak":"normal","lineHeight":"1.5","MozTabSize":"2","OTabSize":"2","tabSize":"2","WebkitHyphens":"none","MozHyphens":"none","msHyphens":"none","hyphens":"none","padding":"1rem","margin":"0.5em 0","overflow":"auto","borderRadius":"0.5rem","marginTop":"1.25rem","marginBottom":0,"border":"1px solid hsl(var(--border))","fontSize":"0.875rem"},"children":["$","code",null,{"style":{"whiteSpace":"pre","fontFamily":"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace"},"children":[false,[["$","span","code-segment-0",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["if"]}],["$","span","code-segment-1",{"style":{},"children":[" since_version "]}],["$","span","code-segment-2",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["is"]}],["$","span","code-segment-3",{"style":{},"children":[" "]}],["$","span","code-segment-4",{"className":"token","style":{"color":"hsl(286, 60%, 67%)"},"children":["not"]}],["$","span","code-segment-5",{"style":{},"children":[" "]}],["$","span","code-segment-6",{"className":"token","style":{"color":"hsl(29, 54%, 61%)"},"children":["None"]}],["$","span","code-segment-7",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[":"]}],["$","span","code-segment-8",{"style":{},"children":["\n"]}],["$","span","code-segment-9",{"style":{},"children":["    query "]}],["$","span","code-segment-10",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["="]}],["$","span","code-segment-11",{"style":{},"children":[" query"]}],["$","span","code-segment-12",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}],["$","span","code-segment-13",{"className":"token","style":{"color":"hsl(95, 38%, 62%)"},"children":["filter"]}],["$","span","code-segment-14",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["("]}],["$","span","code-segment-15",{"style":{},"children":["\n"]}],["$","span","code-segment-16",{"style":{},"children":["        Event"]}],["$","span","code-segment-17",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}],["$","span","code-segment-18",{"style":{},"children":["version "]}],["$","span","code-segment-19",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":["!="]}],["$","span","code-segment-20",{"style":{},"children":[" "]}],["$","span","code-segment-21",{"className":"token","style":{"color":"hsl(29, 54%, 61%)"},"children":["None"]}],["$","span","code-segment-22",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[","]}],["$","span","code-segment-23",{"style":{},"children":["\n"]}],["$","span","code-segment-24",{"style":{},"children":["        Event"]}],["$","span","code-segment-25",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":["."]}],["$","span","code-segment-26",{"style":{},"children":["version "]}],["$","span","code-segment-27",{"className":"token","style":{"color":"hsl(207, 82%, 66%)"},"children":[">"]}],["$","span","code-segment-28",{"style":{},"children":[" since_version"]}],["$","span","code-segment-29",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[","]}],["$","span","code-segment-30",{"style":{},"children":["\n"]}],["$","span","code-segment-31",{"style":{},"children":["    "]}],["$","span","code-segment-32",{"className":"token","style":{"color":"hsl(220, 14%, 71%)"},"children":[")"]}]]]}]}]
4c:["$","p","p-10",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["The ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"version != None"}]," condition is not just defensive — it is load-bearing. Without it, every poll with ",["$","code","code-1",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"since_version=0"}]," re-delivers every pre-migration row. The filter is ",["$","code","code-2",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"AND NOT NULL"}],", not ",["$","code","code-3",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"OR NULL"}],"."]}]
4d:["$","h2","h2-3",{"className":"mt-12 text-2xl font-semibold leading-snug text-foreground first:mt-0","children":"What I learned"}]
4e:["$","p","p-11",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":"The root cause of most version-counter bugs is the assumption that the application layer controls the insertion order. It doesn't — the OS scheduler does. Any two-statement pattern (read-then-write, select-then-insert, check-then-act) can be interleaved by a concurrent request between the two statements."}]
4f:["$","p","p-12",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["The correct mental model: if a value must be unique and increasing across concurrent inserters, let the database assign it. Sequences, identity columns, and ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"ON CONFLICT DO UPDATE RETURNING"}]," are the right tools. Python-side ",["$","code","code-1",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"MAX()+1"}]," is not."]}]
50:["$","p","p-13",{"className":"mt-4 text-base leading-8 md:text-lg first:mt-0 first:text-xl first:leading-relaxed first:text-foreground md:first:text-2xl","children":["The secondary lesson: a NULL guard on the filtered side of an incremental sync is not optional. Pre-migration rows are a permanent fixture of any ",["$","code","code-0",{"className":"rounded bg-secondary px-1.5 py-0.5 text-[0.9em] text-foreground","children":"ADD COLUMN IF NOT EXISTS"}]," migration. The polling consumer must know which rows to skip, and the filter must express that explicitly."]}]
51:["$","div",null,{"className":"mt-14 border-t border-border pt-8","children":["$","$L3",null,{"href":"/platform","className":"inline-flex items-center text-sm font-medium text-primary transition-colors hover:text-primary/80","children":["Start a build",["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":24,"height":24,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-arrow-right ml-2 h-4 w-4","aria-hidden":"true","children":[["$","path","1ays0h",{"d":"M5 12h14"}],["$","path","xquz4c",{"d":"m12 5 7 7-7 7"}],"$undefined"]}]]}]}]
52:["$","aside",null,{"className":"hidden lg:block","children":["$","div",null,{"className":"sticky top-24 space-y-4","children":[["$","h3",null,{"className":"text-xs font-semibold uppercase tracking-wider text-primary","children":["More in ","Database"]}],["$","div",null,{"className":"space-y-4","children":[["$","$L3","bounding-ordered-set-aggregates",{"href":"/blog/bounding-ordered-set-aggregates","className":"block overflow-hidden rounded-lg border border-border bg-card transition-colors hover:border-primary/40","children":[["$","div",null,{"className":"relative aspect-[16/9] overflow-hidden bg-secondary/70","children":[["$","img",null,{"src":"/blog/posts/bounding-ordered-set-aggregates/hero.jpg","alt":"A row of vintage brass and copper rotary valves on an industrial pipe assembly in a dimly lit utility room, one valve partially closed, sharp focus, no people.","className":"h-full w-full object-cover","loading":"lazy","decoding":"async"}],["$","img",null,{"src":"/blog/posts/logo.png","alt":"","aria-hidden":"true","className":"pointer-events-none absolute right-2 top-2 h-[24px] w-[24px] mix-blend-screen"}]]}],["$","div",null,{"className":"p-4","children":[["$","p",null,{"className":"text-xs font-medium text-primary","children":"Database"}],["$","p",null,{"className":"mt-1 text-xs text-muted-foreground","children":["2026-W20"," · ","5 min"]}],["$","p",null,{"className":"mt-2 line-clamp-2 text-sm font-semibold leading-snug text-foreground","children":"Bounding PostgreSQL Ordered-Set Aggregates Before They Eat Your Database"}]]}]]}],["$","$L3","pg-advisory-xact-lock-version-stamp",{"href":"/blog/pg-advisory-xact-lock-version-stamp","className":"block overflow-hidden rounded-lg border border-border bg-card transition-colors hover:border-primary/40","children":[["$","div",null,{"className":"relative aspect-[16/9] overflow-hidden bg-secondary/70","children":[["$","img",null,{"src":"/blog/posts/pg-advisory-xact-lock-version-stamp/hero.jpg","alt":"A heavy metal date stamp poised over a clean white document, ink visible on the stamp rubber, single overhead light.","className":"h-full w-full object-cover","loading":"lazy","decoding":"async"}],["$","img",null,{"src":"/blog/posts/logo.png","alt":"","aria-hidden":"true","className":"pointer-events-none absolute right-2 top-2 h-[24px] w-[24px] mix-blend-screen"}]]}],["$","div",null,{"className":"p-4","children":[["$","p",null,{"className":"text-xs font-medium text-primary","children":"Database"}],["$","p",null,{"className":"mt-1 text-xs text-muted-foreground","children":["2026-W20"," · ","4 min"]}],["$","p",null,{"className":"mt-2 line-clamp-2 text-sm font-semibold leading-snug text-foreground","children":"Atomic Version Counters Without a Sequence — pg_advisory_xact_lock"}]]}]]}]]}],["$","$L3",null,{"href":"/blog?category=database","className":"inline-flex items-center text-sm font-medium text-primary transition-colors hover:text-primary/80","children":["Read all in ","Database",["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":24,"height":24,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-arrow-right ml-2 h-4 w-4","aria-hidden":"true","children":[["$","path","1ays0h",{"d":"M5 12h14"}],["$","path","xquz4c",{"d":"m12 5 7 7-7 7"}],"$undefined"]}]]}]]}]}]
53:["$","$L58",null,{}]
54:["$","script","script-0",{"src":"/_next/static/chunks/94245cbda44972fe.js","async":true}]
55:["$","script","script-1",{"src":"/_next/static/chunks/af778fff4a0f4be6.js","async":true}]
56:["$","script","script-2",{"src":"/_next/static/chunks/b096b037d08e2f31.js","async":true}]
57:["$","$L59",null,{"children":["$","$5a",null,{"name":"Next.MetadataOutlet","children":"$@5b"}]}]
5b:null
