[homepage|forum|cv] WM-097 [text|html] [remarks]
              
Document: WM-097                                                 P. Webb
Category: Tutorial                                            2026-06-22

                    How to migrate from Gel to Disc

Abstract

   The hardest part is getting your data out of Gel in a useable format,
   the rest is easy (but mind your links on the way in, warning near
   the end).

Body

   Dumping your Gel database to a format other databases can read
   requires arcane knowledge but don’t fret, I’ve uncovered the
   incantations to free your data!

   Perform this full backup, for peace of mind.

   

   gel dump --all --format=dir gel-export

You should see something like:

   Connecting to Gel instance 'INSTANCE' at localhost:PORT...
   Starting dump for database `'DATABASE'`...
     Finished dump for `'DATABASE'`. Total size: 181.67 KiB

This will create gel-export in your current directory. Take note of the instance and database names and the port as you’ll need these later. Next, grab the password to your database:

   gel instance credentials --insecure-dsn -I INSTANCE

You should see something like:

   gel:///DATABASE?port=PORT&password=PASSWORD&tls_ca_file=%3C...%3E&tls_security=no_host_verification

Now we can set some variables to make the last bits pseudo-legible. sslmode=require because Gel refuses plaintext connections, and without it psql fails with a misleading auth error before the real "TLS required" one.

   DSN="postgresql://edgedb@localhost:PORT/DATABASE?sslmode=require"


   export PGPASSWORD="PASSWORD"

Gel’s binary dump is useless to anything but Gel, so to get tabular data out we go through its SQL adapter. List the tables into a .tsv first, without any escaping that could mangle the identifiers:

   psql "$DSN" -At -F $'\t' -c "
     SELECT table_schema, table_name
     FROM information_schema.tables
     WHERE table_schema NOT IN ('information_schema', 'pg_catalog')
   " > gel-export/tables.tsv

Create our final export directory:

   mkdir gel-export/data

Finally, we render our .csvs:

   while IFS=$'\t' read -r schema table; do
     out="${schema}_${table}"
     psql "$DSN" --csv -c "SELECT * FROM \"$schema\".\"$table\"" > "gel-export/data/$out.csv"
   done < gel-export/tables.tsv


A quick note on what’s in those CSVs, because it bites at import time (and it bit me)! Gel maps each object type to a table with id and __type__ columns, single properties as plain columns, and (what got me) single LINKS as <link>_id UUID columns (your owner link becomes an owner_id column holding the target’s id). Multi links and multi properties aren’t in these tables at all; they live in their own source/target tables and import as separate files.
I’ll assume you installed Disc[1] already. Great! You’ll need to get it setup with your schema. Run that migration!

   disc migrate

Next, we’ll point Disc at your fresh collection of .csvs:

   disc db import ./gel-export/data

This SHOULD work; it didn’t for me because…

   ✗ Import failed (transaction rolled back): duplicate key value violates unique constraint "log_pkey"

…and that’s irrelevant to me. Ignoring conflicts like this is okay.

   disc db import ./gel-export/data --on-conflict skip


You’ll get an import manifest of what was processed and skipped. Remember those <link>_id columns? Disc resolves them into your single links, but anything it can’t map surfaces here as a warning. Confirm your links got set and that no non-empty column was quietly discarded. A previous version of Disc silently dropped every <link>_id column and because I’m dogfooding this, I found the issue and fixed. This is bleeding edge folks!
Run disc serve and navigate to your database’s /ui and you should see populated objects in the Data tab. Voila! Now all you gotta do is update your codebase…unfortunately, you’ve gotta handle that yourself. 🕸️