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:
- First pass: insert all rows with the cycle column NULL.
- Second pass:
UPDATEto 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).