SynthForge SynthForge SynthForge IO

Integration · PostgreSQL · Neon · Supabase

Generate Postgres test data, with foreign keys intact

Multi-table fixtures that load into local Postgres, Neon, or Supabase with psql and import_postgresql.sql. Free web sessions.

Short answer

Design a multi-table schema in SynthForge, generate, and download the PostgreSQL export. You get import_postgresql.sql (CREATE TABLE, \\copy loaders, then the foreign keys) and per-table CSVs. Every child row references a real parent row by construction. Point psql at local Postgres, Neon, Supabase, or RDS. The tables arrive in a synthforge_import schema rather than public.

See the data

first_name last_name date_of_birth
Tammy Morrow 1969-08-30
Paul Pisacane 1913-10-03
Raymond Leung 1951-01-30
Hildreth Lowery 1918-05-10
Joseph Torres 1950-04-28
Robert Mote 1936-09-25
Kaylee Bean 2023-03-24
Marcella Noha 2010-03-17
Sierra Jenkins 2000-09-11
Monique McGreevy 2006-08-16
Reese Blair 2016-01-18
Montana Friel 2004-05-09

Person names follow US Census and SSA frequencies. First names match birth year on the same row.

Download sample pack customers, products, orders, order_items · SQL + CSV · No signup required

Try these after you load the pack

sql · orphan check (expect 0)
SELECT COUNT(*) AS orphan_orders
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id
WHERE c.customer_id IS NULL;
sql · top surnames
SELECT last_name, COUNT(*) AS n,
       ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 3) AS pct
FROM customers
GROUP BY last_name
ORDER BY n DESC
LIMIT 10;
sql · 1950s first-name cohort
SELECT first_name, COUNT(*) AS n
FROM customers
WHERE EXTRACT(YEAR FROM CAST(date_of_birth AS DATE)) BETWEEN 1950 AND 1959
GROUP BY first_name
ORDER BY n DESC
LIMIT 10;

Why generate rather than hand-roll

Staging and QA databases fail when orders point at missing customers or when seed scripts drift from production shapes. Hand-rolled Faker loops become a second product.

SynthForge topological-sorts tables, generates parents first, and samples foreign keys from IDs that exist. The same schema can also feed DuckDB, MySQL, or agent workflows via hosted MCP.

How to do it

1. Define the schema

Describe tables in plain English, build them in the visual editor, or paste CREATE TABLE DDL. AI forge and SQL import both produce multi-table schemas with single-column foreign keys.

2. Set cardinality (optional)

Use relationship ratios such as "1 to 4 orders per customer" instead of inventing every child row count. Parents generate first; child foreign keys are sampled from real parent IDs.

3. Generate and export PostgreSQL

Pick PostgreSQL as the SQL dialect (or include SQL export in formats). The download ZIP contains import_postgresql.sql (CREATE TABLE, \copy loaders, then ALTER TABLE ADD CONSTRAINT for the foreign keys) and csv/<table>.csv data files. Everything is created inside a synthforge_import schema.

4. Load with psql (local or Neon / Supabase)

Extract the ZIP, cd into the folder so csv/ paths resolve, then run the import script against any Postgres that accepts your connection string. The tables go into a synthforge_import schema, not into public, so pointing this at an existing database will not disturb what is already there.

bash
# Local
createdb myapp_staging
psql -d myapp_staging -f import_postgresql.sql

# Neon / Supabase / RDS (connection string)
psql "$DATABASE_URL" -f import_postgresql.sql

# Then query them by schema, or set the search_path:
#   SELECT count(*) FROM synthforge_import.customers;
#   SET search_path TO synthforge_import;
#
# Want them in public instead? Find and replace
# synthforge_import in the script before you run it.

# The script uses client-side \copy, for example:
#   \copy customers FROM 'csv/customers.csv' WITH (FORMAT csv, HEADER true);
#   \copy orders    FROM 'csv/orders.csv'    WITH (FORMAT csv, HEADER true);

5. (Optional) Agent path

With an API key and hosted MCP, agents can run description_to_dataset, download the ZIP, and you still load with the same import_postgresql.sql. First API key includes 250 free credits; web sessions stay free.

text
# MCP endpoint: https://mcp.synthforge.io/mcp
# Auth: Authorization: Bearer sfk_live_…
# Docs: https://synthforge.io/docs/mcp

Frequently asked questions

Does Postgres enforce the foreign keys?
Yes. SynthForge emits CREATE TABLE with FOREIGN KEY constraints for PostgreSQL, and the data is also referentially valid by construction: child keys are drawn from generated parent IDs, so loads succeed even if you temporarily disable constraint checks for bulk import experiments.
Does this work with Neon and Supabase?
Yes. Use the same import_postgresql.sql with psql and your provider DATABASE_URL. Client-side \copy streams CSVs from your machine, so you do not need server-side filesystem access on Neon or Supabase.
How large a dataset can I generate?
Up to 1,000,000 rows per table and 1,000,000 rows per dataset, plus a 200 MB cap on the generated download and per-account rate limits. The download cap is what binds on wide, text-heavy tables: 25 columns including free text reaches 200 MB at roughly 575,000 rows. A typical 15-column table generates 200,000 rows in about 12 seconds.
Can I use the same schema for DuckDB or MySQL?
Yes. One schema exports to PostgreSQL, MySQL, SQLite, SQL Server, MariaDB, DuckDB, and CockroachDB, plus CSV, JSON, JSONL, and Parquet.
Does SynthForge use my real production data?
No. It generates greenfield data from the schema you provide. It does not ingest or de-identify a live database. For anonymizing real data, use tools like Tonic or NVIDIA NeMo.

Related

Ready to seed staging?

Generate multi-table Postgres data with real foreign keys, then load with one psql command. No credit card for the web app.