Document: WM-095 P. Webb
Category: Project 2026-06-16
I made a database
Abstract
Technically it’s a big fancy wrapper around Postgres but that
still counts!
Body
In December of last year the developers of my favorite database, Gel,
announced[1] they were quitting the project to work for Vercel on
building "the best Python cloud in the world." Six years was a good
run but it wasn’t enough for them to figure out how to turn a profit
after VC money ran out. Alas.
My previous favorite database was RethinkDB[2], though I discovered
it about a year after its creators closed shop. Gel is now in the
hands of the community and while there is a "blessed fork[3]," said
fork hasn’t seen much activity aside from refactored tests.
Having experienced working with a "dead database" before, I had no
interest in revisiting the pain that comes with eventually needing to
grow beyond it. What drew me to RethinkDB and Gel was the built-in
interface they both come with. I’m not a database whiz and I have
zero interest in learning SQL; otherwise I’d use many of the popular
ones. I’m a designer turned developer turned whomever I need to be to
achieve a goal.
With that in mind, I set out to see if I could build the database I
want to use forever.
## Why?
Why waste the tokens building your own thing when you could
contribute to the existing project? Do you understand the deep
inner workings of Postgres and complex database logic? To what end?
What feature necessitates TypeScript over Python? If you’re
consuming the database it doesn’t matter what language the database
itself is in.
I don’t understand Python, but I understand TypeScript well enough to
be productive with it. Deno has proven itself to be more than capable
as a runtime to build upon and create cross-platform executables.
Postgres is the industry standard for databases; you don’t need to be
an expert to know that. You don’t need to understand the language a
database is written in if you’re using an ORM. When your database IS
the ORM however, it’d make sense to understand that.
These questions were posed to me when I presented my intent to the
Gel community on Discord. Which…fair, but I’m not swayed by cynics
(especially when I have a fantastic domain name, disc.sh
is insane).
I regularly used the chatbot in the Gel documentation for
clarification on how to shape my esoteric queries in a way the
database understands. When that stopped working I knew I had to begin
work on Disc.
## How?
The first order of business was going through Gel’s backlog of Github
issues and processing them against Disc’s roadmap. To automate this,
I made a script that uses Github’s API to batch process all 800+
issues. I then got Claude to analyze them; I won’t share the full
matrix because it’s a LOT but here’s the high-level stats from the
analysis I ran in April.
The category breakdown:
- database-core: 1514 issues
- query-language: 852 issues
- migrations: 405 issues
- devtools: 359 issues
- documentation: 292 issues
- performance: 200 issues
- auth: 157 issues
- cli-tooling: 132 issues
- cloud-hosting: 103 issues
- sdk-client: 63 issues
- storage: 29 issues
- unrelated: 24 issues
- compiler: 7 issues
- code-quality: 1 issue
- sql: 1 issue
Of these, 231 issues were deemed of high relevance, 789 issues were
medium relevance, and 1,676 issues were low relevance.
## What?
Merely having feature parity wasn’t worth a new implementation, I
wanted ease of use. I know I’m using a database but I don’t have to
fight against it.
Here are the original Disc features that I’m super excited about.
1. Codegen-free TypeScript query builder
Gel’s TypeScript client requires running
npx @gel/generate edgeql-js after every schema change to
regenerate a typed query builder that must be checked in and kept
in sync. Disc’s query builder is a runtime module; it reads a
schema declaration and returns a structurally-typed builder which
allows schema changes to flow through with no rebuild step.
2. Schema-derived REST surface (auto-generated)
Gel exposes EdgeQL over HTTP and GraphQL via ext::graphql, but
generates no conventional REST surface. REST is the default for
many integrations (locked-down mobile clients, anything that wants
OpenAPI, &c). Disc auto-generates a REST surface from the schema,
runs it through the same access-policy and auth pipeline as EdgeQL
queries, and emits a matching OpenAPI 3.1 spec.
3. Admin UI features
The diff tool watches .disc files in real time and shows the
unsaved-but-edited schema next to the currently applied schema as
a visual diff (added types in green, removed in red, modified with
side-by-side property lists). An "apply" button generates and runs
the migration in-line.
The watcher’s events are streamed over SSE at
/admin/schema-watch; POST /admin/schema-apply runs through the
standard MigrationEngine, so the lock-timeout pragma,
advisory-lock serialization, and unsafe/ambiguous-op gate all
compose for free.
Gel’s UI shows applied schema only; you switch to your editor and
CLI to make changes.
The visual query builder works by picking a root type, checking
the fields and links to include, adding filter rows (field +
operator + value, auto-typed by the field’s SDL scalar), and
setting order / limit / offset.
The synthesized EdgeQL renders live in a side pane; The "run"
button sends it through the same /query endpoint as the
text editor.
Gel’s UI has a text editor with autocomplete and no
visual builder.
The most exciting thing about the Disc UI to me is that it’s
written in Svelte. I’ve been sick of the chokehold React has over
the developer community for at least a decade. Disc, coupled with
my recent GraphiQL UI[4] and GraphQL server[5] releases, means I’m
finally React-free! (Ask your doctor if Svelte is right for you)
4. Single-binary distribution
Self-hosting Gel is an exercise in frustration. It’s always felt
like I was juggling the Gel server, Postgres, and the UI.
Disc ships one binary that contains the Disc server, Postgres,
and the UI. That’s it. I’m a huge fan of Caddy’s single binary
existence and the ease with which I can spin up a new site. Happy
to finally have a database with the same experience.
If you hate UI, you can use Disc without it! Please look at my
pretty pixels though.
5. Deno-permission-aware access policies
Because Disc runs on Deno, every running piece of code has a
runtime permission set that access policies can reference. Disc’s
extensions share the server’s permission set so all checks are
deployment-time gates.
Gel has application-level identity only; its Python/Rust runtime
has no structured permission model to check against.
## Future?
There’s lots left to do! The documentation needs to live on its own
site and I need to figure out Homebrew deployment. If you’re skittish
about using a new database for RealWorld™ Deployment, fret not, I’m
insane and am building a new product using Disc as its backing store
(I actually paused development on said product to get Disc across the
finish line). Disc works well in development but the production story
has yet to be tested.
Follow me on Mastodon[6] or join the Disc board[7] on my forum to
stay up to date. 🕸️