Open source · Postgres · Supabase
Paste your schema.
Get realistic, perfectly-linked data.
Deterministic. Correct on the first run. Every foreign key resolves, every CHECK passes, every run with the same seed is byte-identical. No LLM in the data path.
pip install synth-scalecopy
Try it in the browser ↓
01 · Try it
Playground
Paste Postgres DDL (CREATE TABLE, FKs, CHECKs, enums). Capped at 15 tables / 1,000 total rows / 50 KB. The CLI has no caps. Your DDL is parsed, never executed.
Paste a Postgres connection string (Supabase: Project Settings → Database → Connection string, the Session Pooler one works best).
Before you paste a real connection string
- Read-only.
No write path exists anywhere in this app — only introspection queries against
information_schema/pg_catalog. - Never stored. Used once for this request, then discarded. Not written to disk, not logged, gone once the response is sent.
- SSRF-guarded.
Private, loopback, and internal hosts are rejected before any connection opens
(
dbsafety.py, open source, read it yourself).
Only publicly reachable databases work here, rate-limited to 3/hour since this opens a real connection. For anything on a private network, use the CLI instead — or skip this entirely and paste DDL text on the other tab.
02 · Why
Why not just ask Claude for a seed script?
-
01
Reproducible
An LLM writes you a probably-correct script that changes every time you re-prompt. Synth-Scale is seeded end to end: same seed, same bytes, today, tomorrow, in CI. You can hash the output and assert on it.
-
02
Constraint-correct at scale
Tables are generated in FK dependency order, so every foreign key resolves, composite keys stay unique, and CHECKs are satisfied by construction, then an independent validator re-checks every constraint. 50,000 rows behave exactly like 50.
-
03
Coherent data
Not a random grid:
updated_at ≥ created_at, orders newer than their users, ashippedorder has ashipped_at, Karachi stays in Pakistan, and a few power users own most of the orders, like real production data. -
04
Not a Faker replacement, a layer above it
Faker generates a realistic name, email, or date with zero concept of your schema. We use Faker under the hood for exactly that, then add what you'd otherwise hand-build yourself: parsing your DDL, resolving foreign keys in dependency order, and satisfying every
CHECKandUNIQUEconstraint by construction.
03 · See it break (or not)
What "just ask an LLM" typically looks like
This is illustrative, not a transcript from one specific model or vendor — it's the failure pattern that shows up constantly when a seed script is hand-written or generated without any schema awareness: a foreign key that doesn't actually exist yet. Same shop schema as the playground above.
Typical seed script · breaks
INSERT INTO categories (name, created_at) VALUES
('Electronics', NOW()),
('Home & Garden', NOW()),
('Sports', NOW());
INSERT INTO products
(category_id, product_name, price, stock, created_at)
VALUES
(1, 'Wireless Earbuds', 59.99, 200, NOW()),
(2, 'Garden Hose', 22.50, 80, NOW()),
(4, 'Yoga Mat', 18.00, 150, NOW());
ERROR: insert or update on table "products"
violates foreign key constraint
DETAIL: Key (category_id)=(4) is not present
in table "categories".
Synth-Scale, same schema · real output
INSERT INTO "products"
("id", "category_id", "product_name", "price", "stock", "created_at")
VALUES
(1, 3, 'Wireless Earbuds Pro', 71.99, 127, '2026-01-01T00:12:40'),
(2, 3, 'Running Shorts', 25.99, 996, '2026-01-01T00:37:27'),
(3, 2, 'Single-Origin Coffee Beans', 36.99, 944, '2025-07-07T14:26:53'),
(4, 2, 'Pocket Poetry Anthology', 11.99, 387, '2025-12-23T02:10:08'),
(5, 2, 'Mountain Bike Helmet', 41.99, 80, '2025-11-13T22:52:40');
✓ Every category_id above references a
category that was actually inserted. Not hand-picked — this is unedited output
from synth-scale --ddl shop.sql --seed 42.
04 · CLI
The real tool is the CLI
This page is the demo. The CLI parses your migrations, introspects live Supabase/Postgres schemas, and loads 50k constraint-correct rows straight into your database (proof below ↓). No caps, fully offline.
$ pip install synth-scale
# see it before you seed it: pretty 10-row preview, zero writes
$ synth-scale --ddl schema.sql --rows 100 --preview
# full run: CSV / SQL inserts / direct DB load, deterministic seed
$ synth-scale --ddl schema.sql --rows 1000 --seed 42 --format sql --out ./seed
# point it at a live database instead of a .sql file
$ synth-scale --from-db --db-url postgres://... --rows 1000
Read the docs on GitHub →
05 · Proof
50,000 rows, verified against a real Postgres database
Not a toy schema: UUID primary keys, a composite primary key, a
composite UNIQUE, a self-referencing foreign key, and CHECK
constraints on dates, enums, and cross-column math — the kind of schema that breaks
naive generators.
Reproduce it yourself — same fixture, same seed, same command:
$ pip install synth-scale
$ synth-scale --ddl hard.sql --seed 42 --format sql \
--rows organizations=50,users=2000,categories=30,products=3000,inventory=4000,coupons=500,subscriptions=3000,orders=12000,order_items=25000,audit_log=420
Fixture: tests/fixtures/hard.sql in the repo. Full methodology
and raw numbers: datagen_pkg/docs/postgres.md.
Want to see what the data itself looks like, not just the stats? Try the playground above ↑.
06 · FAQ
Questions people actually ask
Does it use an LLM to generate the data?
No. Every row comes from deterministic, seeded generation: Faker-backed value generation plus constraint-satisfying logic on top. No API calls, no network dependency, no run-to-run drift.
Which databases does it support?
Postgres and Supabase today. DDL parsing, constraint handling, and the "Connect to Supabase" introspection are all Postgres-specific. MySQL and SQLite aren't supported yet.
Is my schema or connection string stored anywhere?
No. Pasted DDL is parsed in memory and discarded once the response is sent. A "Connect to Supabase" connection string is used for a single request and is never logged or written to disk.
What's the difference between this playground and the CLI?
The playground is a capped browser demo: 15 tables, 1,000 rows, no direct writes to your database. The CLI has no caps and can load rows straight into your own database.
Can I use it in CI?
That's the main use case. pip install synth-scale, run it against your schema with a
fixed seed, and assert on deterministic output.
Is it free?
Yes. The CLI is open source and free. This playground is a free demo of the same engine.
07 · Feedback
Would you actually use this?
Two questions, no email required. Tells us whether to keep building this or go do something else with our time.
08 · Contact
Send us a message
Questions, bug reports, feature requests. Goes straight to the maintainer.
09 · Stay in the loop
Get launch updates
PyPI release, Supabase introspection, CI data contracts. One email when it ships. Nothing else.