I didn't plan a migration. I just noticed we were paying for two databases.
This whole thing started with a very unglamorous realization:
We were paying for Aiven Postgres…
and also paying for Railway.
At some point I opened the Railway dashboard properly and thought:
"Wait — why aren't we using this for the database too?"
No incident. No outage. No scaling crisis.
Just mild financial confusion.
The decision wasn't really "should we migrate?"
It was more like:
"We're already using Railway for everything else. Why is the database emotionally living somewhere else?"
So I did what any developer does when something feels inconsistent: I turned it into a migration project.
The migration itself was weirdly easy
I expected:
- scripts
- downtime planning
- CSV exports
- at least one regretful late-night rollback
Instead, Railway just pointed me to their Postgres migrator:
The setup was:
- Source: Aiven Postgres URL
- Destination: Railway Postgres
- Action: Deploy
That's it. I didn't trust it at first.
The one thing that actually tripped me up
Before the migrator worked, I hit a version mismatch. Railway's Postgres was running v18 — and the migrator requires source and destination to be on the same major version. Aiven was v17, so I had to upgrade it first before anything else would proceed.
Once versions matched, there was another quiet gotcha: two optional environment variables — NO_ACL and NO_OWNER — had to be set to true for the migration to complete cleanly.
| Variable | What it does |
|---|---|
NO_ACL |
Skips restoring access privileges (GRANT/REVOKE commands) |
NO_OWNER |
Skips restoring object ownership (ALTER OWNER commands) |
The Railway docs show their default as true, but in practice they were false — meaning the migrator was trying to restore ACLs and ownership from Aiven, hitting permission errors, and failing silently enough that it wasn't immediately obvious why.
Setting both to true explicitly is what actually made it work.
I kept waiting for something to break. Nothing did.
- No data loss.
- No partial sync weirdness.
- No "why is production dead" moment.
Just a working database in a new place, which is almost more stressful than failure — because you keep checking if you missed something.
Railway vs Aiven (honest experience, not a benchmark)
Aiven Postgres:
- Solid and reliable
- More manual setup
- External to your deployment ecosystem
- SSL and config overhead you have to manage
Railway Postgres:
- Lives inside your deployment environment
- Internal networking by default
- Less cognitive overhead on config
- Everything in one dashboard
The biggest difference wasn't performance. It was mental overhead. Fewer places to check. Fewer credentials to rotate. One less tab permanently open.
Would I recommend this?
If you're already on Railway and running an external Postgres for no strong reason — probably yes. The migrator genuinely works, the internal networking is a real quality-of-life upgrade, and the consolidation is worth it just to stop context-switching between dashboards.
If you have a strong reason for keeping the database external (compliance, specific Aiven features, multi-cloud setups) — that calculus changes. But "we started there and never questioned it" isn't a strong reason.
Sometimes the migration is just noticing you forgot to consolidate.

Top comments (0)