Mustafa Nevfel

Software architecture

Boundaries, data models and the decisions that decide whether a system survives its tenth feature.

  1. 8 min read

    An invoice is a snapshot, not a calculation

    Why recomputing invoice totals from current rules breaks, and how to freeze integer minor-unit amounts, rule versions and document numbers in PostgreSQL.

  2. 8 min read

    Design the reconnect first: sequence numbers, replay and snapshots

    Real-time bugs live in the seconds after a connection comes back. A resume protocol built on sequence numbers, idempotent replay and snapshots.

  3. 8 min read

    Run AI agents like queue workers: briefs, budgets and stop reasons

    How I run AI coding agents like queue workers: written briefs, narrow tools, hard budgets, idempotent writes, typed stop reasons and review gates.

Snippets

  1. Snippet · TypeScript

    Bounded AI agent loop with step, token, time and error budgets

    Check every budget before each step, share one AbortSignal with the model call and the tools, and end with a typed out_of_budget that names the limit.

  2. Snippet · SQL

    Gapless invoice numbering in PostgreSQL without a sequence

    Increment a counter row with UPDATE ... RETURNING inside the issuing transaction: the row lock orders issuers and a rollback gives the number back.

  3. Snippet · TypeScript

    Derive idempotency keys for AI agent tool calls

    Hash the task id, tool name and canonical arguments in the harness, and pass the key to the system that owns the side effect, not only to a local ledger.

  4. Snippet · SQL

    Make issued invoices immutable in PostgreSQL

    A BEFORE UPDATE OR DELETE trigger catches mistakes, privileges enforce it, and corrections are linked credit notes with a derived adjusted total.

  5. Snippet · SQL

    Gap-free per-stream sequence numbers in PostgreSQL

    Bump a counter row per stream in the same transaction as the change; the row lock makes sequence order equal commit order, with no gaps.

  6. Snippet · TypeScript

    Resume a WebSocket stream after reconnect without losing messages

    On reconnect, subscribe with buffering first, then replay the gap or send a snapshot, then drain the buffer. The reverse order loses messages.