# drawDB and the cost of a schema that only lives in one browser profile

> drawDB is a browser ERD editor and SQL generator under AGPL-3.0, and its own configuration files show what it will not do for you: nothing syncs your diagram, there is no version to pin, and a shared instance needs a second repository running beside it.

**drawdb-io/drawdb** — drawDB is a free browser-based database diagram editor and SQL generator for building ERDs, exchanging SQL scripts and creating migrations without an account.

- Repository: https://github.com/drawdb-io/drawdb
- Website: https://drawdb.app
- Stars: 39,718 · Forks: 3,270
- Language: JavaScript
- License: AGPL-3.0
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/drawdb-io-drawdb

## The diagram lives in a browser database and nothing syncs it

package.json lists dexie ^3.2.4 and dexie-react-hooks ^1.1.7, a browser side database binding and its React hooks, and no dependency in that list points at a hosted store for your schema. The README says the editor works without creating an account. Those two facts line up: the schema is a local artifact held in the browser profile, not a row on somebody's server.

Here is the cost. A diagram exists on one machine, in one browser profile. Clearing site data, opening a private window, or switching to another laptop takes the schema with it, and no login exists that could bring it back. The only copy that survives is whatever you export by hand, which is why the export path matters more in this tool than in one with server side storage. Nothing in the repository names an autosave interval, a backup file, or a recovery path, so treat a browser data wipe as data loss rather than an inconvenience.

## nginx writes config.js at container start, so a URL change means a restart

The Dockerfile has two stages. The first is node:20-alpine running npm ci with NODE_OPTIONS="--max-old-space-size=4096" set before npm run build, which emits /app/dist. The second stage copies that dist into nginx:stable-alpine3.23 on port 80. The interesting part is a location block for /config.js that returns a window.__DRAWDB_CONFIG__ object assembled from two environment variables and served with Cache-Control "no-store", while / falls through to index.html through try_files.

Because nginx expands those variables when it renders the template at startup, the backend URL is never baked into the JavaScript bundle. That is what lets the README add a server to an image you already have:

```bash
docker run -p 3000:80 -e VITE_BACKEND_URL=https://your-drawdb-server.example.com ghcr.io/drawdb-io/drawdb:latest
```

The URL lives in the container environment, not in the files, so changing it means recreating the container. Note also that VITE_GIST_BACKEND_URL appears in that nginx template while .env.sample carries a single line, VITE_BACKEND_URL=http://backend.com. Sharing to gists has no sample configuration anywhere in the repository, and config.js offers no other switch either.

## compose.yml starts the Vite dev server, not the nginx image

compose.yml defines one service on node:20-alpine, publishes 5173:5173, bind mounts the checkout to /var/www/html, and runs sh -c "npm install && npm run dev -- --host". Read that command and you know the file is a contributor setup: hot reload, sources on the host, dependencies installed inside the container on every start. It is not the production path.

Production is a different pair of commands, and the port does not match:

```bash
docker build -t drawdb .
docker run -p 3000:80 drawdb
```

So a compose habit carried into production leaves you reading about 5173 while the image listens on 80 behind port 3000, and a fresh compose project answers on 5173 with a dev server you did not ask for. The compose file also sets no VITE_BACKEND_URL, which means sharing is off in that setup, and because the tree is bind mounted, the host directory ends up collecting the container's node_modules.

## The 4 GB build heap flag exists only inside the Dockerfile

The build stage sets NODE_OPTIONS="--max-old-space-size=4096" before running the build, and the local instructions do not. Vite is required at ^8.1.0, and the client bundle pulls in tailwindcss ^4.0.14, @monaco-editor/react, @dbml/core and jsonschema together, so the build is memory hungry by design. If a local build dies with an out of memory error, that flag is the first thing to try and the Dockerfile is where the value is written down.

```bash
git clone https://github.com/drawdb-io/drawdb
cd drawdb
npm install
npm run dev
```

The two install commands also differ. The image uses npm ci, which follows package-lock.json exactly, while these lines use npm install, which can rewrite the lockfile and pull newer minor releases than the ones baked into the published image. For a self hosted copy meant to reproduce upstream, npm ci is the closer match, and the lockfile in the repository is the reason that works.

## Version 0.0.0 and no releases means there is nothing to pin

package.json carries "version": "0.0.0" and "private": true, and the repository publishes no GitHub releases. Combined with the image tag ghcr.io/drawdb-io/drawdb:latest, every install tracks whatever main held at the moment you built. There is no version to write into a runbook, no changelog to read when an export format changes, and no clean way to separate a regression you introduced from one that arrived upstream.

The repository is not archived and the last push to main is dated 2026-09-26, so the code is active, but active is not the same as versioned. The private flag also means there is no npm package to install from, so a global install is not an option and every deployment is either a clone or a container. If you deploy this, write the commit hash into your own notes. Without releases, the pull is the upgrade, and the diff is the only change record you will get.

## The export stack implies more formats than you can find written down

package.json carries jspdf ^4.2.1, jszip ^3.10.1, file-saver ^2.0.5, html-to-image, @dbml/core ^3.13.9 and jsonschema ^1.4.1. Each one is an output format or a validator, so the running app can hand you more than a picture and a SQL script. None of it is enumerated in the repository, which points at drawdb.app and leaves the feature list to the hosted site.

The consequence is that a self hosted build cannot be documented from its own files, and a hosted feature page can describe a user interface newer than the commit you are running. The same gap covers SQL. The parsers in the tree are node-sql-parser ^5.4.0 and oracle-sql-parser ^0.1.0, and the project mentions generating migrations without naming a single dialect. Oracle coverage rests on a package still inside its 0.x line, and nothing in the repository tells you which of your existing dumps survive a round trip. Assume none until you check your own schema.

## AGPL-3.0 attaches to the copy other people can reach

LICENSE is AGPL-3.0, and the project ships both a Docker image and a route to a separate drawdb-server repository for the sharing feature. The AGPL network clause is the part teams trip over, because it attaches to conveying the running program rather than the file you downloaded. An internal instance reachable by colleagues can fall under it once you modify it.

So the line is not distribution, it is modification plus network reach, and an unmodified copy you run for yourself sits on the other side of it from a modified copy you expose to other users. Nothing in the repository adds commercial or enterprise terms on top, and the version field is 0.0.0, so there is no enterprise license to buy your way out of the question. Read LICENSE before you fork this into anything shared, keep the notice in the deployment, and if the sharing feature matters, budget for running drawdb-server alongside it.

## A self hosted image still ships the Vercel analytics script

package.json lists @vercel/analytics ^1.2.2 among runtime dependencies, and vercel.json sits at the repository root, so the primary deployment target is Vercel even when you serve the bundle from your own nginx. The Docker build copies the entire dist directory into the image, so anything the bundler put in that JavaScript goes into your image as well.

Nothing in the README, the .env.sample file, or the nginx template switches it off, and config.js carries only backendUrl and gistBackendUrl, so runtime configuration offers no analytics switch either. If your instance sits on an isolated network or under a policy that forbids third party calls, the bundle still contains the client that would make them, and removing it means editing the dependency list and rebuilding rather than setting a flag. That is a small change, but it is a change, and it belongs in your build notes next to the commit hash.

## Conclusion

drawDB fits someone sketching a schema in a browser tab, and it is a poor fit as shared team infrastructure. Walk away if your schemas must survive a machine swap, if you need a build you can pin, or if the AGPL network clause around a shared internal instance would need legal review. Before deploying, record the commit you built, run your own SQL dump through import and export to see what survives, and find out what the jspdf, jszip and @dbml/core dependencies actually give you.

## FAQ

### Is drawdb free to use?

The project describes itself as a free, simple, and intuitive online database diagram editor and SQL generator, ships under AGPL-3.0, and points to drawdb.app as the hosted entry point. Nothing in the repository describes a paid tier, a seat limit, or a feature that is held back.

### how to use drawdb

For local work, clone the repository, run npm install, then npm run dev, and Vite serves the editor from your checkout. The hosted copy sits at drawdb.app, and the project states you can build diagrams without creating an account.

### What is the best tool for creating ERD diagrams?

The repository does not rank tools, and it never names a competitor. What it does show is the shape of this one: a browser ERD editor under AGPL-3.0 that works without an account, keeps state through dexie in package.json, and ships jspdf, jszip, html-to-image and @dbml/core for output.

### drawdb vscode

There is no VS Code extension, command line tool, or editor integration anywhere in this repository. The delivered forms are a browser app at drawdb.app, a local Vite dev server, and a Docker image that serves static files through nginx.

### Can I generate an ER diagram from SQL online for free?

The project presents itself as a database entity relationship diagram editor in the browser that can export and import SQL scripts, so SQL to diagram is the advertised path. SQL parsing runs through node-sql-parser and oracle-sql-parser, and no dialect list appears anywhere in the repository, so test a round trip with your own dump before relying on it.

### drawdb vs dbdiagram

The repository contains no comparison of the two. drawDB sends readers to drawdb.app for its own feature list and never names dbdiagram, so any side by side you find has to come from somewhere outside this project.

## Sources

- [Official documentation](https://drawdb.app)
- [Official README](https://github.com/drawdb-io/drawdb#readme)
- [Project repository](https://github.com/drawdb-io/drawdb)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/drawdb-io-drawdb
