Database Schema Designer — Visual ERD Builder for PostgreSQL, MySQL & SQLite

Free visual database schema designer and ERD builder. Define tables, fields, and foreign key relationships. Generate SQL DDL, Prisma schema, Drizzle schema, and TypeORM entities — all in your browser with no sign-up required.

← Software Engineering
About this tool — how it works & FAQOpen ▾Close ▴

About Database Schema Designer

Database Schema Designer is a free, browser-based visual ERD builder. Create tables, define fields with types and constraints, draw foreign key relationships, and instantly generate production-ready SQL DDL for PostgreSQL, MySQL, or SQLite — plus ORM schemas for Prisma, Drizzle, and TypeORM. No account, no backend, no install required. The pre-loaded Blog Platform example (users, posts, comments) shows the full feature set in one glance.

Table and field editor

The left sidebar lists all tables in your schema. Click a table to select it, double-click the name to rename it inline, and hit the ✕ button to delete. The center panel shows every field in the selected table. Each field row has a name input, a type dropdown (UUID, VARCHAR(255), TEXT, INTEGER, BIGINT, DECIMAL(10,2), BOOLEAN, TIMESTAMP, JSON), and constraint checkboxes — PK (primary key), NN (not null), UQ (unique). A Default value input lets you set database-level defaults. Toggle the FK button to open the foreign key section: pick the referenced table and column from dropdowns populated from your live schema. Add or remove fields with the + Add Field button and the ✕ on each row.

ERD visual panel

The right sidebar renders all tables as stacked ERD cards in real time. Each card shows the table name in a sky-blue header, then lists every field with small badge icons for its constraints (PK, FK, NN, UQ), the field name, and the data type. Foreign key fields show a gray annotation "→ tablename.column" so relationships are visible at a glance without drawing lines. The panel scrolls independently and updates instantly as you edit any table or field.

SQL DDL generator

The bottom code panel (toggled with "Show Code") generates dialect-correct CREATE TABLE statements. PostgreSQL uses UUID DEFAULT gen_random_uuid(), TIMESTAMP WITH TIME ZONE DEFAULT NOW(), and REFERENCES tablename(column) ON DELETE CASCADE for foreign keys. MySQL uses CHAR(36) for UUID, INT AUTO_INCREMENT, and DATETIME DEFAULT CURRENT_TIMESTAMP. SQLite uses TEXT for UUID, INTEGER PRIMARY KEY AUTOINCREMENT, and TEXT for most flexible types. All three dialects emit proper CONSTRAINT … FOREIGN KEY … REFERENCES syntax. Click the Copy button to grab the full schema in one keystroke.

ORM schema generators — Prisma, Drizzle, TypeORM

Prisma tab: emits a valid schema.prisma with datasource db { provider = "postgresql" } (or mysql / sqlite), generator client { provider = "prisma-client-js" }, and a model block per table. FK fields are typed with relation scalars and @relation() decorators pointing at the correct model and fields.

Drizzle tab: emits a TypeScript file using drizzle-orm table builders — pgTable / mysqlTable / sqliteTable — with typed column helpers (uuid, text, varchar, integer, boolean, timestamp, jsonb). FK columns use .references(() => tableName.column).

TypeORM tab: emits TypeScript @Entity() classes with @PrimaryGeneratedColumn('uuid'), @Column() with correct type options, and @ManyToOne() / @OneToMany() relation decorators. All imports from 'typeorm' are included. Switch dialect with the PostgreSQL / MySQL / SQLite tabs at the top and the ORM output updates instantly.

Frequently asked questions

Is the Prisma schema output valid and ready to use?

Yes. The generated schema.prisma is syntactically valid and follows current Prisma conventions. It includes the datasource block (provider matches your selected dialect), the generator block for prisma-client-js, and a model block for each table. FK relationships are expressed with the correct @relation syntax including fields: [] and references: [] arrays. You can paste it into your project's prisma/schema.prisma file and run npx prisma migrate dev immediately. Review auto-generated relation names and add cascade delete options (@relation(onDelete: Cascade)) if you want to match the SQL DDL's ON DELETE CASCADE.

Which ORM should I choose for a new Next.js project in 2026?

Prisma remains the most popular choice for Next.js + Supabase or Next.js + PlanetScale stacks — excellent DX, automatic migrations, and a fully-typed client that catches errors at compile time. Drizzle is gaining ground fast for edge deployments (Cloudflare Workers, Vercel Edge) because it ships no binary, has a smaller bundle, and produces SQL you can read and debug easily. TypeORM is mature and widely used in NestJS backends but is heavier for simple Next.js use cases. Short answer: use Prisma for a new project unless you need edge runtime support or prefer writing SQL-like queries, in which case Drizzle is the modern pick.

Can I use the generated SQL directly in Supabase?

Yes. Select the PostgreSQL dialect, open the generated SQL tab, copy the output, and paste it into the Supabase SQL Editor (project → SQL Editor → New query). Run it to create your tables. The schema uses gen_random_uuid() which is available in Supabase's PostgreSQL without any extension. If you want Row Level Security policies (required for multi-user apps), add ENABLE ROW LEVEL SECURITY on each table and write policies after the schema is created — the SaaS Builder Lab on EngineersUniverse generates those policies automatically.

How do I model a many-to-many relationship?

Many-to-many relationships (e.g., posts and tags, users and roles) require a junction table. Create a third table (e.g., post_tags) with two FK columns: post_id referencing posts.id and tag_id referencing tags.id. Make both fields NOT NULL. Optionally add a composite primary key across both columns, or use a surrogate UUID PK plus a UNIQUE constraint on (post_id, tag_id). In Prisma you can use implicit many-to-many (a @relation field on both models and Prisma generates the junction table) or explicit many-to-many (define the junction model yourself for extra columns like assigned_at). In Drizzle and TypeORM always define the junction table explicitly.

Should I use soft deletes or hard deletes?

Hard deletes (DELETE FROM …) permanently remove rows and keep the database clean. Soft deletes add a deleted_at TIMESTAMP column — a null value means active, a timestamp means deleted — and every query adds WHERE deleted_at IS NULL. Use soft deletes when: audit trails are required (regulatory, financial), deleted data may need restoration without backups, or related records reference the deleted row and you want to preserve history. Use hard deletes for ephemeral data (sessions, logs, temporary records) or when storage cost matters at scale. Soft deletes add complexity: every query must filter deleted_at, unique constraints must include deleted_at or use partial indexes, and ORMs need global query scopes to avoid leaking deleted data. Prisma supports soft deletes via middleware; Drizzle and TypeORM require manual WHERE clauses or a query-builder wrapper.

Related tools & guides