{
  "generated_at": "2026-06-13T03:46:06.625Z",
  "embeddings_url": "/zfn/embeddings.json",
  "notes": [
    {
      "id": 0,
      "ref": "ZFN-0",
      "title": "Engineering Field Notes",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "meta",
        "process"
      ],
      "summary": "What Field Notes are, why I write them, and how they work — numbered, status-tracked notes on building software well, published openly and importable as JSON and raw markdown.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/0-engineering-field-notes.md",
      "url": "/zfn/0-engineering-field-notes/",
      "raw_url": "/zfn/0-engineering-field-notes.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 1,
      "ref": "ZFN-1",
      "title": "Keep engineering decision records",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "process",
        "meta"
      ],
      "summary": "Record significant engineering decisions as short, versioned markdown files — context, decision, consequences. Write one for cross-team contracts, directional principles, hard-to-reverse choices, and conventions others must follow. Cite them instead of re-arguing.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/1-engineering-decision-records.md",
      "url": "/zfn/1-engineering-decision-records/",
      "raw_url": "/zfn/1-engineering-decision-records.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 2,
      "ref": "ZFN-2",
      "title": "Engineering priority ordering",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "principles",
        "process"
      ],
      "summary": "When concerns conflict, prioritize security > correctness > availability > performance — and never trade a higher-ranked concern for a lower one. The rule binds the moment you must choose. Cite it instead of re-arguing it.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/2-engineering-priority-ordering.md",
      "url": "/zfn/2-engineering-priority-ordering/",
      "raw_url": "/zfn/2-engineering-priority-ordering.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 3,
      "ref": "ZFN-3",
      "title": "Default-encrypt internal service traffic",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "infra",
        "transport"
      ],
      "summary": "All external traffic is TLS, no exceptions. Internal traffic is encrypted by default; an internal call site may skip transport encryption (never authentication) only under a documented, audited carve-out anchored to a network-perimeter guarantee.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/3-default-encrypt-internal-traffic.md",
      "url": "/zfn/3-default-encrypt-internal-traffic/",
      "raw_url": "/zfn/3-default-encrypt-internal-traffic.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 4,
      "ref": "ZFN-4",
      "title": "Incident tooling must not depend on what it recovers",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "principles",
        "reliability",
        "incident",
        "security",
        "infra"
      ],
      "summary": "Anything you need to respond to an incident — deploy/rollback, kill switches, observability, break-glass access — must not depend, directly or transitively, on the systems likely to be down during it. Never gate incident tooling behind a system it might need to recover.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/4-incident-tooling-independence.md",
      "url": "/zfn/4-incident-tooling-independence/",
      "raw_url": "/zfn/4-incident-tooling-independence.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 5,
      "ref": "ZFN-5",
      "title": "Make workload identity a platform-owned service",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "auth",
        "infra",
        "platform"
      ],
      "summary": "Workload identity belongs in shared platform infrastructure, not reimplemented per service. A small token service mints short-lived tokens any service verifies. Shared keys are a fine first step; asymmetric signing the better end-state — don't let 'no PKI' block it.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/5-platform-workload-identity-service.md",
      "url": "/zfn/5-platform-workload-identity-service/",
      "raw_url": "/zfn/5-platform-workload-identity-service.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 6,
      "ref": "ZFN-6",
      "title": "Bind tokens to a key: sender-constrained tokens (DPoP)",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "auth",
        "http"
      ],
      "summary": "A bearer token grants access to whoever holds it — steal it, replay it. Bind the token to a holder key (DPoP, RFC 9449) so using it requires proving possession of a private key the token names. A stolen token alone becomes useless.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/6-sender-constrained-tokens-dpop.md",
      "url": "/zfn/6-sender-constrained-tokens-dpop/",
      "raw_url": "/zfn/6-sender-constrained-tokens-dpop.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 7,
      "ref": "ZFN-7",
      "title": "Sign the message, not just the session (HTTP Message Signatures)",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "auth",
        "http"
      ],
      "summary": "A bearer token proves nothing about the request it rides on. Sign the message itself (HTTP Message Signatures, RFC 9421) — request, and ideally response — so the recipient can prove who sent this exact message and not a byte changed. Shared keys first; asymmetric better.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/7-sign-the-message.md",
      "url": "/zfn/7-sign-the-message/",
      "raw_url": "/zfn/7-sign-the-message.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 8,
      "ref": "ZFN-8",
      "title": "Don't hide behind anonymous 'people'",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "culture",
        "leadership",
        "communication",
        "ic"
      ],
      "summary": "Never invoke unnamed 'people' to carry weight — 'a few people are concerned', 'some think'. It launders one view as phantom consensus and makes the listener argue a crowd they can't see. Name them and bring them in, or own it. If they can't speak up, fix the culture.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/8-dont-speak-for-anonymous-people.md",
      "url": "/zfn/8-dont-speak-for-anonymous-people/",
      "raw_url": "/zfn/8-dont-speak-for-anonymous-people.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 9,
      "ref": "ZFN-9",
      "title": "No long-lived cloud keys; workloads authenticate by federated identity",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "auth",
        "infra",
        "cloud"
      ],
      "summary": "No static AWS or GCP keys anywhere — not in code, secret stores, or env. Workloads use their runtime's own identity and cross clouds by exchanging it (OIDC) for short-lived credentials via federation. Static keys are a documented carve-out only.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/9-no-long-lived-cloud-keys.md",
      "url": "/zfn/9-no-long-lived-cloud-keys/",
      "raw_url": "/zfn/9-no-long-lived-cloud-keys.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 10,
      "ref": "ZFN-10",
      "title": "Pin the expected owner on cross-account resource calls (confused-deputy defense)",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "infra",
        "cloud",
        "auth"
      ],
      "summary": "Authority to call a resource isn't proof it's the one you meant. Any call crossing an account boundary must assert the expected owner: ExpectedBucketOwner on S3, aws:ResourceAccount conditions, validation of untrusted ARNs, plus inbound trust pinned with SourceArn/ExternalId.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/10-verify-resource-owner.md",
      "url": "/zfn/10-verify-resource-owner/",
      "raw_url": "/zfn/10-verify-resource-owner.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 11,
      "ref": "ZFN-11",
      "title": "Route outbound HTTP through an isolated egress proxy",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "infra",
        "network",
        "ssrf"
      ],
      "summary": "Application compute shouldn't make arbitrary outbound HTTP — it's an SSRF pivot to internal services and the cloud metadata endpoint. Route all egress through a proxy (SOCKS, or a gRPC egress service) on isolated compute with no route inward. The proxy's network is the boundary.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/11-outbound-http-egress-proxy.md",
      "url": "/zfn/11-outbound-http-egress-proxy/",
      "raw_url": "/zfn/11-outbound-http-egress-proxy.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 12,
      "ref": "ZFN-12",
      "title": "Queues, topics, and journals are different tools — don't conflate them",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "infra",
        "messaging",
        "events",
        "reliability"
      ],
      "summary": "Queues (competing consumers), topics (fan-out), and journals (ordered, replayable logs) give different guarantees. Don't conflate them; a pipeline often uses several. Prefer journals over topics, but not where head-of-line blocking hurts. With queues, bound the concurrency.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/12-queues-topics-journals.md",
      "url": "/zfn/12-queues-topics-journals/",
      "raw_url": "/zfn/12-queues-topics-journals.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 13,
      "ref": "ZFN-13",
      "title": "Fail fast and push back: retries, load shedding, and flow control",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "reliability",
        "architecture",
        "infra",
        "resilience"
      ],
      "summary": "Build client retries (backoff, jitter, Retry-After) from day one. Under overload, shed fast and push the failure back to the source to retry — don't retry internally and amplify it. Flow-control everywhere, bound every queue, and don't take more work than you can finish in time.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/13-load-shedding-and-flow-control.md",
      "url": "/zfn/13-load-shedding-and-flow-control/",
      "raw_url": "/zfn/13-load-shedding-and-flow-control.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 14,
      "ref": "ZFN-14",
      "title": "Define every API with a schema, and generate the clients",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "api",
        "process",
        "correctness"
      ],
      "summary": "Define every API with a machine-readable schema (OpenAPI, Protobuf, GraphQL) as the source of truth, and generate clients and server stubs from it — never hand-roll request-building and JSON parsing. Hand-written clients drift and break silently; check schema compatibility in CI.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/14-schema-first-apis-generate-clients.md",
      "url": "/zfn/14-schema-first-apis-generate-clients/",
      "raw_url": "/zfn/14-schema-first-apis-generate-clients.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 15,
      "ref": "ZFN-15",
      "title": "Partition customer data by tenant from day one",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "data",
        "multi-tenancy",
        "scalability",
        "security"
      ],
      "summary": "Make customer data tenant-partitioned from day one: tenant-scope every query, never join across tenants, route through a tenant→location directory. Run one physical database at first — but keep the model shardable. Retrofitting isolation onto a shared DB is brutal.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/15-partition-customer-data-by-tenant.md",
      "url": "/zfn/15-partition-customer-data-by-tenant/",
      "raw_url": "/zfn/15-partition-customer-data-by-tenant.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 16,
      "ref": "ZFN-16",
      "title": "Separate the data plane from the control plane",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "infra",
        "reliability",
        "scalability"
      ],
      "summary": "Split the serving path (data plane) from the management path (control plane). The data plane keeps serving on last-known-good config when the control plane is down — never call it on the hot path. Coupling them turns a control-plane bug into a serving outage.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/16-separate-data-plane-control-plane.md",
      "url": "/zfn/16-separate-data-plane-control-plane/",
      "raw_url": "/zfn/16-separate-data-plane-control-plane.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 17,
      "ref": "ZFN-17",
      "title": "Separate configuration, state, and ephemeral data",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "data",
        "multi-tenancy",
        "design"
      ],
      "summary": "Customer data splits into mostly-static config, durable state, and ephemeral sessions — different access, durability, and change rates. Model and store each separately. For bounded static config, prefer loading one validated snapshot held in memory over fetching on demand.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/17-separate-config-state-ephemeral.md",
      "url": "/zfn/17-separate-config-state-ephemeral/",
      "raw_url": "/zfn/17-separate-config-state-ephemeral.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 18,
      "ref": "ZFN-18",
      "title": "Enforce a quota at ingress on every endpoint — even unabused ones",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "reliability",
        "security",
        "api",
        "infra",
        "multi-tenancy"
      ],
      "summary": "Put a quota on every endpoint and enforce it at ingress from day one — per tenant, principal, IP — even for endpoints nobody abuses yet. Unlimited-by-default means the first runaway client or compromised key is an outage. Return 429 + Retry-After; retrofitting limits is painful.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/18-enforce-quotas-at-ingress.md",
      "url": "/zfn/18-enforce-quotas-at-ingress/",
      "raw_url": "/zfn/18-enforce-quotas-at-ingress.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 19,
      "ref": "ZFN-19",
      "title": "Annotate read-only and idempotent endpoints; make every mutation idempotent",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "api",
        "reliability",
        "architecture",
        "correctness"
      ],
      "summary": "Annotate every endpoint as read-only (safe) or idempotent, in the schema, so infrastructure can retry, route to replicas, and cache safely. Make every state-changing endpoint idempotent (idempotency keys for create/charge/send); a non-idempotent retry double-applies.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/19-annotate-readonly-idempotent-endpoints.md",
      "url": "/zfn/19-annotate-readonly-idempotent-endpoints/",
      "raw_url": "/zfn/19-annotate-readonly-idempotent-endpoints.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 20,
      "ref": "ZFN-20",
      "title": "The simplest-looking system is often the most complex to live with",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "data",
        "design",
        "philosophy"
      ],
      "summary": "The system that's simplest to stand up often isn't simplest to live with — it skips the correctness edge cases, so bugs and inconsistency surface fast. A more deliberate design has more parts but fewer surprises, and is often the simpler one over time.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/20-deliberate-complexity-is-often-simpler.md",
      "url": "/zfn/20-deliberate-complexity-is-often-simpler/",
      "raw_url": "/zfn/20-deliberate-complexity-is-often-simpler.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 21,
      "ref": "ZFN-21",
      "title": "Cache only immutable objects; treat caches as tech debt",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "data",
        "performance",
        "reliability"
      ],
      "summary": "Use caches sparingly, only for immutable addressed objects — never for mutable DB results, where invalidation bugs and stale reads live; use projections instead. A cache in the data path is usually a patch over an architectural gap that trades correctness for performance.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/21-caches-sparingly-immutable-only.md",
      "url": "/zfn/21-caches-sparingly-immutable-only/",
      "raw_url": "/zfn/21-caches-sparingly-immutable-only.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 22,
      "ref": "ZFN-22",
      "title": "Quarantine bad architecture behind an interface, then replace it",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "refactoring",
        "design",
        "process"
      ],
      "summary": "When a subsystem is complex and badly architected, quarantine it at its seam: write a clean adapter interface over the mess so the rest of the system depends on the contract, then build a better implementation behind it and expose the new interface directly.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/22-extract-complexity-at-the-seam.md",
      "url": "/zfn/22-extract-complexity-at-the-seam/",
      "raw_url": "/zfn/22-extract-complexity-at-the-seam.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 23,
      "ref": "ZFN-23",
      "title": "Rewriting an implementation is fine — refactoring isn't always the answer",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "process",
        "refactoring",
        "llm"
      ],
      "summary": "Refactoring isn't always right. When the structure is wrong at the root, it's fine — often better — to rewrite an implementation from scratch. Clean interfaces and data models make the implementation disposable: stable contract, swappable internals. LLMs make it cheaper still.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/23-iterate-and-rewrite-implementations.md",
      "url": "/zfn/23-iterate-and-rewrite-implementations/",
      "raw_url": "/zfn/23-iterate-and-rewrite-implementations.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 24,
      "ref": "ZFN-24",
      "title": "One transactional store per write; propagate changes asynchronously",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "data",
        "reliability",
        "consistency"
      ],
      "summary": "Commit each logical write to exactly one transactional store; update other systems via reliable ordered async events — never a synchronous write across two stores, and never 2PC. With a relational primary the WAL is your replayable journal; write events into the same transaction.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/24-one-transactional-store-per-write.md",
      "url": "/zfn/24-one-transactional-store-per-write/",
      "raw_url": "/zfn/24-one-transactional-store-per-write.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 25,
      "ref": "ZFN-25",
      "title": "Track the version a client has seen for read-your-writes",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "data",
        "consistency",
        "api"
      ],
      "summary": "For read-your-writes across backends, track the latest version a client has seen — a token or vector clock. Return it on write; reads then go to a backend at least that fresh. Hold it client-side (a token they present) or server-side (a gateway tracks the session and routes).",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/25-read-your-writes-version-token.md",
      "url": "/zfn/25-read-your-writes-version-token/",
      "raw_url": "/zfn/25-read-your-writes-version-token.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 26,
      "ref": "ZFN-26",
      "title": "AI-assisted content needs no disclaimer, only a human who can back it",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "principles",
        "process",
        "llm"
      ],
      "summary": "Using an LLM to draft engineering content — chat, commits, PRs, docs, comments — is fine and needs no disclaimer. The obligation is human co-signing: every word under your name is one you drove, reviewed, and can defend. Disclose when the ideas are the model's, not yours.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/26-ai-assisted-content-cosign.md",
      "url": "/zfn/26-ai-assisted-content-cosign/",
      "raw_url": "/zfn/26-ai-assisted-content-cosign.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 27,
      "ref": "ZFN-27",
      "title": "Don't tolerate assholes — but be strict about what one is",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "culture",
        "leadership",
        "communication",
        "ic"
      ],
      "summary": "Don't tolerate assholes — people who demean, belittle, punch down. But filter hard on the word: disagreeing, raising ideas, or opening a competing PR isn't being an asshole, it's the work. Assholes attack people; colleagues attack problems. Don't let the label silence dissent.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/27-no-assholes-strict-definition.md",
      "url": "/zfn/27-no-assholes-strict-definition/",
      "raw_url": "/zfn/27-no-assholes-strict-definition.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 28,
      "ref": "ZFN-28",
      "title": "Capability without understanding: brute-force LLM PRs",
      "kind": "open",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "llm",
        "culture",
        "process",
        "learning"
      ],
      "summary": "An open problem: people brute-force PRs with LLMs in domains they don't understand, taking on more than their knowledge supports — and the struggle that used to teach them is smoothed away. How do we stop un-understood code without killing learning or banning a good tool?",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/28-llm-brute-force-prs-understanding.md",
      "url": "/zfn/28-llm-brute-force-prs-understanding/",
      "raw_url": "/zfn/28-llm-brute-force-prs-understanding.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 29,
      "ref": "ZFN-29",
      "title": "Blameless culture, taken seriously — and its one hard line",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "culture",
        "leadership",
        "incident",
        "reliability",
        "process"
      ],
      "summary": "When something breaks, support the person, don't blame. Run post-mortems with ceremony and learn at every level — software, org, culture, process, even solo. Blameless protects honest mistakes, not dishonesty: evading or blaming gets coached; hiding evidence is a firing offense.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/29-blameless-culture-with-a-hard-line.md",
      "url": "/zfn/29-blameless-culture-with-a-hard-line/",
      "raw_url": "/zfn/29-blameless-culture-with-a-hard-line.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 30,
      "ref": "ZFN-30",
      "title": "Use the standard; don't reinvent the protocol",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "security",
        "api",
        "interop"
      ],
      "summary": "When a standard exists for a common or complex problem, use it — don't reinvent the protocol. Standards encode huge adversarial expertise, especially in auth and crypto; a partial implementation beats rolling your own. You're not that special, and your problem isn't either.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/30-use-standards-dont-reinvent.md",
      "url": "/zfn/30-use-standards-dont-reinvent/",
      "raw_url": "/zfn/30-use-standards-dont-reinvent.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 31,
      "ref": "ZFN-31",
      "title": "Own your components — when you deeply understand the domain",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "process",
        "llm",
        "design"
      ],
      "summary": "Owning your own components rather than generic off-the-shelf services is often the better path as you grow: own what's core, lean on small vetted libraries for the hard parts. LLMs make it attainable at smaller scale — but only when you truly understand the domain, or it hurts.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/31-own-your-components.md",
      "url": "/zfn/31-own-your-components/",
      "raw_url": "/zfn/31-own-your-components.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 32,
      "ref": "ZFN-32",
      "title": "Commit to one cloud, and go all-in native",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "infra",
        "cloud"
      ],
      "summary": "Cloud-independence is a false benefit: portability is the least common denominator, costing you the native services that are the point. For end products you run: commit to one cloud, go all-in native. Libraries, software others run, LLM-embeddables, and edge code are exempt.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [
        "32-commit-to-one-cloud-aws"
      ],
      "source": "src/content/notes/32-commit-to-one-cloud.md",
      "url": "/zfn/32-commit-to-one-cloud/",
      "raw_url": "/zfn/32-commit-to-one-cloud.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 33,
      "ref": "ZFN-33",
      "title": "Are LLMs swinging us away from prepackaged services?",
      "kind": "signal",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "llm",
        "architecture",
        "open-source",
        "industry"
      ],
      "summary": "A signal: LLMs may be swinging build-vs-buy away from prepackaged services. A generic complex service used to beat building until real scale; now building what you need is cheap. Maybe open source becomes shared architectures an LLM implements per user — like C replaced ASM.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/33-moving-away-from-prepackaged-services.md",
      "url": "/zfn/33-moving-away-from-prepackaged-services/",
      "raw_url": "/zfn/33-moving-away-from-prepackaged-services.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 34,
      "ref": "ZFN-34",
      "title": "A resource-free 'bouncer' account: the single gateway to customer resources",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "infra",
        "cloud",
        "aws",
        "multi-tenancy"
      ],
      "summary": "Funnel access to customer resources through one dedicated account that holds no resources. Customer trust names only its role; the role is denied from your own org (aws:ResourceOrgID). Fenced both ways, it shrinks the confused-deputy surface to one audited gateway.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/34-resource-free-bouncer-account.md",
      "url": "/zfn/34-resource-free-bouncer-account/",
      "raw_url": "/zfn/34-resource-free-bouncer-account.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 35,
      "ref": "ZFN-35",
      "title": "Reference secrets in config; dereference, refresh, and re-fetch",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "infra",
        "config",
        "reliability"
      ],
      "summary": "Don't put secret values in config — store a reference (a path in a secret store) and dereference it at runtime via your workload identity. Refresh on a signal or expiry so rotation needs no redeploy; re-fetch on auth failure so a rotated secret self-heals.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/35-dereference-secrets-not-store-in-config.md",
      "url": "/zfn/35-dereference-secrets-not-store-in-config/",
      "raw_url": "/zfn/35-dereference-secrets-not-store-in-config.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 36,
      "ref": "ZFN-36",
      "title": "An untested backup is not a backup — test it by restoring",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "reliability",
        "infra",
        "incident",
        "operations"
      ],
      "summary": "An untested backup is a hope, not a backup — the only thing that counts is a restore. Rehearse restores regularly (game days), measure and meet your RTO/RPO, automate them, and cover the whole recovery path — data, schema, config, secrets, cutover — not just the dump.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/36-test-backups-by-restoring.md",
      "url": "/zfn/36-test-backups-by-restoring/",
      "raw_url": "/zfn/36-test-backups-by-restoring.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 37,
      "ref": "ZFN-37",
      "title": "Every lock is a lease",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "infra",
        "reliability",
        "consistency"
      ],
      "summary": "A lock that can outlive its holder is a deadlock scheduled for later. Give every lock — including informal ones like claimed_by columns — a TTL, a named owner, and a heartbeat; make expiry automatic and server-side; fence the side effects so a stale holder can't corrupt anything.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/37-every-lock-is-a-lease.md",
      "url": "/zfn/37-every-lock-is-a-lease/",
      "raw_url": "/zfn/37-every-lock-is-a-lease.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 38,
      "ref": "ZFN-38",
      "title": "Agents are principals: delegate, never impersonate",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "auth",
        "llm",
        "architecture"
      ],
      "summary": "An agent acting with a copied user credential is impersonation — untraceable by design. Give agents their own identities and keys; let them act for a human only through explicit, scoped, time-bounded, revocable delegation; and record both actor and principal on every action.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/38-agents-are-principals.md",
      "url": "/zfn/38-agents-are-principals/",
      "raw_url": "/zfn/38-agents-are-principals.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 39,
      "ref": "ZFN-39",
      "title": "Break loops, not spirals",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "events",
        "reliability",
        "llm"
      ],
      "summary": "Event-driven and agentic systems echo. A loop — a lineage recurring with the same data — produces nothing new; detect it with runtime-stamped provenance and break it loudly. A spiral — recurring with new data — is legitimate work; bound it with budgets, never loop-breakers.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/39-break-loops-not-spirals.md",
      "url": "/zfn/39-break-loops-not-spirals/",
      "raw_url": "/zfn/39-break-loops-not-spirals.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 40,
      "ref": "ZFN-40",
      "title": "No anonymous \"system\" actor",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "security",
        "auth",
        "infra",
        "operations"
      ],
      "summary": "If \"system\" appears as an actor in your audit log, attribution is already broken. Every automated action — cron job, cleanup task, migration, agent — runs as a named identity with its own credentials and scope, so \"who did this?\" has an answer and revocation is surgical.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/40-no-anonymous-system-actor.md",
      "url": "/zfn/40-no-anonymous-system-actor/",
      "raw_url": "/zfn/40-no-anonymous-system-actor.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 41,
      "ref": "ZFN-41",
      "title": "Make the technical choice you can put your name behind",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "leadership",
        "culture",
        "process",
        "decisions"
      ],
      "summary": "When two options would both work, it's fine to choose the one your experience lets you put your name behind, and to resist pressure that isn't about the merits — vendor incentives, politics, top-down preference. Owning the call costs capital up front; being right repays it.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/41-choices-you-can-put-your-name-behind.md",
      "url": "/zfn/41-choices-you-can-put-your-name-behind/",
      "raw_url": "/zfn/41-choices-you-can-put-your-name-behind.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 42,
      "ref": "ZFN-42",
      "title": "My one cloud is AWS",
      "kind": "conviction",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "infra",
        "cloud",
        "aws"
      ],
      "summary": "Applying the one-cloud principle (ZFN-32), my pick is AWS — 100%, a league of its own. Go native: skip Kubernetes, use ECS; lean into SQS, SNS, Kinesis, IAM, ALB, RDS. The one exception to native — provision with OpenTofu, not CloudFormation, now that LLMs write .tf so well.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/42-my-one-cloud-is-aws.md",
      "url": "/zfn/42-my-one-cloud-is-aws/",
      "raw_url": "/zfn/42-my-one-cloud-is-aws.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 43,
      "ref": "ZFN-43",
      "title": "Name your systems as archetypes, not machinery",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "architecture",
        "design",
        "culture",
        "communication"
      ],
      "summary": "Names shape thought: a good name compresses a system's purpose, boundaries, and temperament into a word. Name the long-lived cast as archetypes — a Sentinel, a Seer — not Rule Engine and Decision Service. Bureaucratic names flatten judgment; a character must live up to its role.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/43-name-systems-as-archetypes.md",
      "url": "/zfn/43-name-systems-as-archetypes/",
      "raw_url": "/zfn/43-name-systems-as-archetypes.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 44,
      "ref": "ZFN-44",
      "title": "Burnout is a conditions problem, not a workload problem",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "culture",
        "ic",
        "principles"
      ],
      "summary": "Burnout was never about the hours. I've woken up excited on 100-hour weeks and drowned in thirty-hour ones; the variable is the conditions, not the workload. The red flags I watch for, the six pillars that make intensity sustainable, and the levers I pull at the first tremor.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/44-burnout-is-conditions-not-workload.md",
      "url": "/zfn/44-burnout-is-conditions-not-workload/",
      "raw_url": "/zfn/44-burnout-is-conditions-not-workload.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    },
    {
      "id": 45,
      "ref": "ZFN-45",
      "title": "Read the standards; better yet, help write them",
      "kind": "note",
      "status": "current",
      "date": "2026-06-12",
      "updated": null,
      "authors": [
        "Theo Zourzouvillys"
      ],
      "tags": [
        "interop",
        "learning",
        "industry",
        "principles"
      ],
      "summary": "Learn to read standards docs — RFCs, W3C recs — fluently; they're the primary source, not a last resort. Even better, get involved: reading them well makes you a sharper builder, and helping write them is the best protocol education there is.",
      "supersedes": null,
      "superseded_by": null,
      "aliases": [],
      "source": "src/content/notes/45-read-the-standards.md",
      "url": "/zfn/45-read-the-standards/",
      "raw_url": "/zfn/45-read-the-standards.md",
      "embeddings": [
        {
          "model": "voyage-4",
          "dimensions": 1024,
          "generated_at": "2026-06-13",
          "stale": false
        }
      ]
    }
  ]
}