
finally cracked full airtable to supabase migration (formulas, rollups, linked records, attachments)
migrating off airtable into postgres sounds like it should be a solved problem by now. it really isn't, and the reasons why are more interesting than i expected when i started.
the trap most people fall into:
first instinct is usually csv export. doesn't work. linked records come out as comma-separated record ids text, not relationships. you've moved data, not structure.
second instinct is a python script against the airtable api. this gets you about 60% of the way and then collapses under its own weight. you end up having to:
- detect which links are one-to-many vs many-to-many and build junction tables for the latter
- figure out insert order so foreign keys actually resolve instead of erroring out
- map airtable field types to postgres equivalents (some have no clean mapping)
- pull attachments before their urls expire
- do something reasonable with formulas, rollups, and lookups
why sync tools aren't actually a migration
whalesync and sequin both work and i don't want to take anything away from them they're solid at what they do. but the thing that took me a while to internalize is that they sync computed values, not the logic that produced them. so postgres ends up holding a number that airtable calculated. modify a linked record on the postgres side and nothing recalculates. only airtable still knows the formula. the new value syncs back over from airtable.
practical implication: you can't actually cancel airtable. you're locked into paying for it forever, or your "migrated" data goes stale the moment it changes.
the post-migration problem that surprised me
once everything lands in postgres with proper junction tables and foreign keys, the schema is correct but the experience of working with it is much worse than airtable. one airtable row that showed you names, computed totals, and linked record titles becomes a 3-4 table join in sql. correct, but you've lost the at-a-glance view your team has been using for years.
what worked for me: generating a layer of postgres views during the migration that recompose the table back into something readable. linked record names appear inline, rollups show as computed columns, lookups resolve. the underlying schema stays normalized, the views just give you a familiar way to look at it.
formulas were the biggest time sink
airtable's formula language isn't sql and has enough quirks that direct translation isn't always possible. i kept grinding on it and got to roughly 80% coverage on the common patterns text functions, date arithmetic, math, logical operators, most if/switch logic, the typical record-level stuff. these map cleanly to postgres expressions or generated columns. the last 20% is genuinely airtable-specific behavior that needs a human call. but 80% means you're reviewing and editing, not rewriting.
what i'm building
atmigrator handles this end-to-end as a one-shot migration. formulas and rollups become real postgres logic. linked records become proper foreign keys with junction tables where needed. attachments get pulled and rehosted before urls expire. views get generated on top so the destination doesn't feel alien.
anyone who's migrated off airtable into supabase or any postgres host, how did you handle the formula side specifically? rewrite by hand, accept static values from sync, or something else? trying to understand what people actually need.