DocsConcepts

Foreign keys

How seedkit guarantees referential integrity, even with composite keys, deferred constraints, and cycles.


Faker doesn't know about foreign keys. Hand-written factories tend to break the moment a schema gets non-trivial. Seedkit's whole insertion model is FK-first.

The dependency graph

Before any data is generated, seedkit builds a directed graph of FK dependencies between tables. We then run topological sort to determine insertion order. Parents go first; children reference them.

For a schema like:

orgs   ← users (org_id)
users  ← deals (owner_id), deals (org_id via users)
deals  ← activities (deal_id)

Insert order: orgs → users → deals → activities.

Composite keys

Seedkit treats composite primary keys as units. If (org_id, user_id) is your PK in a memberships table, both columns are populated together — never one without the other.

Cycles

Some schemas have cycles. The classic case is a self-reference:

CREATE TABLE users (
  id           bigint PRIMARY KEY,
  invited_by   bigint REFERENCES users(id) -- cycle!
);

Seedkit handles cycles in two passes:

  1. First pass: insert all rows with the cycle column NULL.
  2. Second pass: UPDATE to populate the FK from already-inserted siblings.

If your FK is NOT NULL, mark the constraint DEFERRABLE INITIALLY DEFERRED — seedkit will insert with the constraint deferred and check at end of transaction.

Deferred constraints

Schemas using DEFERRABLE INITIALLY DEFERRED constraints are first-class. We respect the deferral and verify all constraints at the end of the transaction. If you have circular NOT NULL FKs that aren't deferrable, seedkit will warn at preview time.

Verifying integrity

Run seedkit preview to see the FK satisfaction report:

Topo sort...        ✓ 8 tables, 14 relations
Detecting cycles... ✓ 1 self-ref (users.invited_by)
Generating rows...  ✓ 14,820 rows
Resolving FKs...    ✓ 0 orphans

FK report:
  orgs   → users          14820/14820 ✓
  deals  → orgs, owners   3240/3240 ✓
  users  → users (self)   9182/9182 ✓ (deferred)

Zero orphans means every FK column has a valid parent.

See also

  • seedkit preview — see the FK report without inserting.
  • Synthetic data — how the FK columns are populated (lookup from already-inserted parents).