§00|The log

field notes from the satus team.


  1. Cost estimates are guardrails, not accounting

    Our dry-run estimator quotes two cents for a 125-row seed. Three real 125-row runs cost seven hundredths of one. The 31x gap is deliberate, and here is the arithmetic.

    • ·llm
    • ·cost
    • ·cli
    • ·openai
    • ·telemetry
    6 min
  2. Structured output from Claude without a JSON parser

    How satus forces typed rows out of the Messages API with tool_choice, how that differs from OpenAI's json_schema, and the Anthropic feature that landed after we built ours.

    • ·llm
    • ·anthropic
    • ·openai
    • ·structured-output
    • ·cli
    6 min
  3. The cycle-breaking heuristic we documented and never shipped

    In May we published a four-rule heuristic for choosing which foreign key to defer. Running it against the shipped binary this week, three of the four rules do not exist.

    • ·postgres
    • ·foreign-keys
    • ·audit
    • ·cli
    5 min
  4. v0.3.11: two claims the code did not support

    Run telemetry is now opt-in, which is what our security page always said. And primary keys are read from pg_catalog, so a read-only CI role no longer gets a false green from --dry-run.

    • ·release
    • ·cli
    • ·privacy
    • ·postgres
    4 min
  5. information_schema is privilege-filtered, and it made our CI gate lie

    A role with SELECT on every table in the schema still sees zero constraints in information_schema. Measured on PostgreSQL 16.13, including the bug it exposed in our own dry-run gate.

    • ·postgres
    • ·catalogs
    • ·introspection
    • ·privileges
    • ·ci
    9 min
  6. v0.3.10: the 24-hour license grace is now real

    satus 0.3.10 makes license verification honest — activation stores the key, generate re-verifies stale verdicts, and a canceled subscription now actually loses paid caps within 24 hours.

    • ·release
    • ·cli
    • ·licensing
    2 min
  7. v0.3.9: the safety feature you couldn't turn off

    Yesterday's safety guard had no escape hatch in the GitHub Action. Plus exit code 10, and what a line-by-line audit of our own docs turned up.

    • ·release
    • ·cli
    • ·github-actions
    • ·docs
    4 min
  8. v0.3.8: the safety guard we had already written about

    satus 0.3.8 implements the 10,000-row production guard our docs have described since v0.3.x. It was documented, linked, and explained. It was never in the code.

    • ·release
    • ·cli
    • ·postgres
    • ·safety
    5 min
  9. v0.3.7: five bugs, four of them silent

    satus 0.3.7 fixes identity columns, foreign keys to non-PK columns, a TRUNCATE that reached outside the run set, two cost numbers that disagreed, and telemetry that broke our privacy promise.

    • ·release
    • ·cli
    • ·postgres
    • ·privacy
    6 min
  10. v0.3.6: one fix, for a footgun we stepped on ourselves

    satus 0.3.6 normalizes ANTHROPIC_BASE_URL so both the SDK convention (no /v1) and the previous satus convention (with /v1) work. No other changes.

    • ·release
    • ·anthropic
    • ·cli
    2 min
  11. Triggers I have loved and hated

    Audit, denormalization, and validation triggers each break a Postgres seed run differently. What actually happens, measured on PostgreSQL 17.9.

    • ·postgres
    • ·triggers
    7 min
  12. The schema I couldn't reproduce

    Schema reproduction is the hardest maintenance task we have. A field note on the two bugs that took longest to reproduce, and the four artifacts we now use to shorten the loop.

    • ·support
    • ·tooling
    • ·postgres
    7 min
  13. Postgres extensions that trip up seeders

    PostGIS wants valid geometries. pgvector wants meaningful embeddings. pgcrypto wants real ciphertext. None of the three accept random bytes.

    • ·postgres
    • ·extensions
    6 min
  14. What a bad profile looks like

    Three profile drafts we threw away before shipping saas, ecommerce, and b2b. Too many knobs, distributions that did not compose, vertical leaks.

    • ·profile
    • ·methodology
    • ·anti-pattern
    5 min
  15. Seeding Stripe-shaped data without Stripe

    How to fill a billing schema with realistic Customer, Subscription, Invoice, and Charge rows locally, so dashboards render without touching test-mode Stripe.

    • ·billing
    • ·stripe
    • ·patterns
    8 min
  16. When UUIDs aren't the answer

    UUIDv7 made the primary-key debate interesting again. What v7 fixes, what it doesn't, and when bigserial or a composite key is still the honest choice for a Postgres schema.

    • ·postgres
    • ·primary-keys
    7 min
  17. What pg_dump doesn't tell you about your own schema

    pg_dump is a backup tool, not a schema description. Three things it omits or reorders, and why a seeder should read pg_catalog directly instead.

    • ·postgres
    • ·introspection
    • ·pg_dump
    11 min
  18. v0.3.5: automated npm publishing, two correctness fixes

    satus 0.3.5 adds tag-triggered npm publishing with provenance, restores deferrable-FK detection in introspection, and fixes the Action selftest to validate the in-repo CLI.

    • ·release
    • ·ci
    • ·github
    • ·npm
    4 min
  19. v0.3.3: the GitHub Action, and opt-in failure fingerprints

    satus 0.3.3 ships passkeybridge/satus/packages/action@main, a composite Action wrapping the CLI for PR-preview databases, plus opt-in schema-shape fingerprints for the v0.4.0 agent eval set.

    • ·release
    • ·ci
    • ·github
    • ·telemetry
    6 min
  20. Generated columns are load-bearing now

    Postgres GENERATED columns moved from novelty to infrastructure once PG12 shipped STORED and PG18 shipped VIRTUAL. What that means for introspection, INSERT ordering, and seeders.

    • ·postgres
    • ·generated-columns
    • ·schema
    • ·seeding
    10 min
  21. Profile design 101: pick distributions, not values

    The heuristic we use when adding a new vertical to satus. Name the distributions and the correlations first, then, and only then, sample values. An internal design doc, published.

    • ·profile
    • ·methodology
    • ·distributions
    • ·postgres
    • ·seeding
    12 min
  22. Roadmap: v0.3.3 ships the GitHub Action, and v0.5 becomes v0.4

    What the next satus release will and will not do, why the GitHub Action is a 0.3.x patch and not a 0.4 line item, and how the version numbers shift.

    • ·roadmap
    • ·ci
    • ·github
    • ·release
    7 min
  23. The 1am deploy that only failed in prod

    A field note on why a query that ran in 4ms on a seeded dev database stalled the moment it hit real cardinality, and what the planner was actually looking at.

    • ·postgres
    • ·planner
    • ·performance
    • ·seeding
    5 min
  24. Arrays vs junction tables: when Postgres arrays are a smell

    Postgres array columns are tempting, occasionally correct, and usually a junction table waiting to happen. A field guide to the three cases where arrays win and the four where they don't.

    • ·postgres
    • ·modeling
    • ·seeding
    8 min
  25. Inside the saas-subscriptions profile: MRR, churn, and the dunning death spiral

    Subscription lifecycles, plan changes, failed payments, and the states no one documents. What the satus saas-subscriptions profile recommends, and what it leaves to you.

    • ·profile
    • ·saas
    • ·billing
    • ·postgres
    • ·seeding
    15 min
  26. Seeding into a multi-tenant schema without leaking tenants

    Multi-tenant schemas leak in seed data through shared lookup tables, FK chains that drop tenant_id, and RLS bypassed by a superuser connection. Here is the discipline satus follows.

    • ·postgres
    • ·multi-tenant
    • ·rls
    • ·seeding
    • ·security
    10 min
  27. Agent mode, postponed to v0.5

    Why satus is shipping an opt-in agent mode in v0.5 instead of v0.3, what it will and will not do, and how the 90-day evidence window between now and then shapes the design.

    • ·roadmap
    • ·agents
    • ·design
    • ·postgres
    7 min
  28. Enum types that grew up

    How Postgres enum types evolve in real schemas, why ALTER TYPE ADD VALUE is harder than it reads, and how satus picks realistic distributions over them.

    • ·postgres
    • ·enums
    • ·schema
    • ·seeding
    9 min
  29. v0.3.0: Anthropic as a first-class provider, and machine-readable output

    Anthropic joins OpenAI as a peer provider via tool-use forcing. A new --json flag emits a single snake_case object on stdout so CI can parse it. Token counts are now persisted alongside cost.

    • ·postgres
    • ·satus
    • ·release
    • ·anthropic
    • ·openai
    • ·cli
    5 min
  30. A $0 dry-run that catches FK and constraint bugs before the LLM call

    satus 0.3 ships an offline --dry-run that simulates LLM output and validates against your live Postgres metadata. No API key, no writes, no spend.

    • ·postgres
    • ·seeding
    • ·validation
    • ·ci
    4 min
  31. When faker.js is exactly the wrong answer

    faker.js generates 10,000 plausible names. It does not generate 10,000 names whose foreign keys resolve. A field note on the gap between fake values and seed data.

    • ·tooling
    • ·faker
    • ·postgres
    • ·seeding
    • ·philosophy
    9 min
  32. Check constraints that lie

    Postgres CHECK constraints look like rules but often encode wishes. Where they leak (NULL, non-immutable expressions, NOT VALID, domains), why satus has to detect it, and what to write instead.

    • ·postgres
    • ·constraints
    • ·schema
    • ·seeding
    11 min
  33. Inside the e-commerce profile: SKUs, carts, and the long tail of returns

    Catalog distributions, basket sizes, return rates, and seasonality the satus e-commerce profile encodes, what it leaves to the user, and why we do not ship a fashion-vs-electronics switch.

    • ·profile
    • ·ecommerce
    • ·distributions
    • ·postgres
    • ·seeding
    14 min
  34. Three timezone bugs we found by seeding production-shaped data

    Uniformly random timestamps hide timezone bugs. Business-hours-clustered timestamps surface them. Three bugs we have reproduced in support, and the catalog signals that predict each one.

    • ·postgres
    • ·timezones
    • ·testing
    • ·seeding
    12 min
  35. JSONB columns that are secretly relational

    Half the JSONB columns we see are key/value bags. The other half are foreign keys in disguise — arrays of IDs pointing at real rows, with no constraint to prove it. How to tell them apart.

    • ·postgres
    • ·jsonb
    • ·modeling
    • ·seeding
    8 min
  36. v0.2.0: deferred constraints, faster planning, and a smaller binary

    Cyclic foreign keys now seed end-to-end via deferred constraints and a post-insert wire-up pass. Catalog introspection drops from five round-trips to one. The npm tarball is 77.6% smaller.

    • ·postgres
    • ·satus
    • ·release
    • ·foreign-keys
    • ·performance
    7 min
  37. The CITEXT trap

    A seed job asked for 10,000 users and inserted 6,200. The unique index on a CITEXT column folded Alice and alice into one row. What CITEXT does, why new schemas avoid it, and what satus generates.

    • ·postgres
    • ·citext
    • ·unique
    • ·collations
    • ·seeding
    8 min
  38. Partitioned tables meet RLS, and nobody wins

    RLS policies on a partitioned parent do not protect the children. We hit this in two customer schemas last week. Here is what Postgres actually does, and the two-line workaround satus now prints.

    • ·postgres
    • ·rls
    • ·partitioning
    • ·seeding
    8 min
  39. Inside the medical-booking profile: why appointments are harder than they seem

    Appointments cluster around mid-morning and afternoon, never at 3am, almost never on holidays, and trail a long tail of no-shows. What the satus medical-booking profile encodes, and why.

    • ·profile
    • ·medical
    • ·distributions
    • ·postgres
    • ·seeding
    11 min
  40. NULL vs NOT NULL is not the question

    A support ticket about a nullable column that broke an app. The real question is what NULL means to your code, and Postgres gives you three answers, not two.

    • ·postgres
    • ·null
    • ·semantics
    • ·seeding
    7 min
  41. Introducing the satus log

    A plain-text changelog and field notebook for schema-aware seed data, written for engineers who read RFCs for fun.

    • ·meta
    • ·postgres
    2 min
  42. Cyclic foreign keys in the wild

    Most seed-data tools pretend cycles don't exist. They do. Here is how satus splits the graph, inserts with NULLs, and back-patches in a second pass.

    • ·postgres
    • ·foreign-keys
    • ·graphs
    • ·seeding
    6 min
§01|Subscribe

RSS, no email required.


We do not run a newsletter. The full feed lives at /blog/rss.xml. Add it to any reader. There are no tracking pixels in the feed and no cookies on this site.