Back to Blog
Managed Database Service 12 min read

TL;DR

  • Fly.io provides no built-in database GUI — a forum thread states "it is extremely hard to test or interact with postgres on fly.io."
  • The standard approach is flyctl proxy to forward a local port, then connect a desktop client — requires CLI tools on every device.
  • Deploying pgAdmin as another Fly app adds $3-5/month in compute costs and requires configuring internal networking.
  • DBEverywhere connects to Fly.io Postgres through a static IP — add it to your Fly app's public services and connect from any browser in 60 seconds.
  • Free tier: 5 sessions/month, 20-minute timeout. Paid: $5/mo for unlimited sessions, saved connections, and SSH tunnel support.

Table of Contents

Fly.io Postgres GUI: The Database Management Tool Fly Doesn't Give You

Fly.io has earned a loyal following among developers who want to deploy applications close to their users across 35+ regions worldwide. Its lightweight VM-based architecture (powered by Firecracker) and developer-friendly CLI make it one of the most approachable platforms for deploying containerized apps. But when it comes to managing the PostgreSQL database that often accompanies those apps, the experience breaks down.

A Fly.io community forum thread captures the frustration directly: "it is extremely hard to test or interact with postgres on fly.io." The thread, with numerous replies and reactions, describes developers struggling with basic tasks like viewing table data, running queries, and debugging their database — tasks that take seconds with a GUI on other platforms.

This article is for Fly.io developers who want a Fly.io Postgres GUI without the friction of the current workarounds. We will walk through three approaches: the built-in CLI proxy, deploying a GUI as a separate Fly app, and using a browser-based tool that sidesteps Fly.io's networking complexity entirely.

How Fly.io Postgres works (and why external access is hard)

To understand why getting a GUI connected to Fly.io Postgres is difficult, you need to understand how Fly.io handles databases.

Fly.io Postgres is not a managed database. Fly.io repeatedly states this in their documentation. When you run fly postgres create, Fly provisions a VM running PostgreSQL inside a Fly app. You get a PostgreSQL instance, but Fly does not manage backups, failover, upgrades, or monitoring for you. It is a convenience layer for running Postgres in a Fly VM — not a managed database service like AWS RDS, DigitalOcean Managed Databases, or Neon.

More importantly for GUI access: Fly.io Postgres databases are not publicly accessible by default. They run on Fly's private network (6PN — a WireGuard-based internal mesh) and are only reachable from other Fly apps in the same organization. There is no public IP, no open port, and no way to connect from outside Fly's network without explicitly setting up access.

This networking model is secure by design. Your database is never exposed to the internet. But it creates a significant barrier for any external tool — whether that is pgAdmin on your laptop, DBeaver on a colleague's machine, or a browser-based service like DBEverywhere.

There are three main ways to bridge this gap, each with increasing levels of practicality.

Method 1: flyctl proxy + desktop client

The official recommendation from Fly.io is to use flyctl proxy to create a WireGuard tunnel from your local machine to the Fly.io Postgres instance.

fly proxy 15432:5432 -a your-postgres-app

This command forwards local port 15432 to port 5432 on your Fly Postgres app. You can then connect a desktop client (pgAdmin, DBeaver, TablePlus) to localhost:15432 with your Postgres credentials.

What works: - Secure — traffic is encrypted over WireGuard - No changes to your Fly app configuration - Your database stays completely private

What does not work:

Every developer needs flyctl installed. The Fly CLI is the only way to establish the proxy. Every person who needs database access must install flyctl (a Go binary — small, but still requires installation and authentication), have a Fly.io account in the same organization, and run the proxy command before connecting their client.

Every developer needs a desktop client. On top of flyctl, you need pgAdmin, DBeaver, TablePlus, or another PostgreSQL GUI installed locally. That is two tools minimum before you can look at your data.

It does not work on mobile, tablets, or locked-down machines. If you are on a device where you cannot install flyctl or a desktop database client, you have no access. Corporate laptops with restricted software policies, borrowed machines, or tablets are all excluded.

The proxy must stay running. If you close the terminal or the proxy process crashes, your connection drops. There is no persistent access.

Each session requires the proxy. There is no "set it up once and forget it." Every time you need database access, you open a terminal, run the proxy command, wait for it to connect, then open your database client.

For a solo developer on their primary machine, this workflow is tolerable. For a team of 5-10 developers who need occasional database access, it becomes a support burden.

Method 2: Deploy pgAdmin as a Fly app

Since Fly.io Postgres is accessible from other Fly apps on the same internal network, you can deploy a database GUI as another Fly app. pgAdmin is the most common choice.

A minimal fly.toml for pgAdmin looks like:

[build]
  image = "dpage/pgadmin4:latest"

[env]
  PGADMIN_DEFAULT_EMAIL = "admin@yourdomain.com"
  PGADMIN_DEFAULT_PASSWORD = "your-pgadmin-password"

[[services]]
  internal_port = 80
  protocol = "tcp"

  [[services.ports]]
    port = 443
    handlers = ["tls", "http"]

Deploy with fly launch and pgAdmin runs alongside your app, with direct internal network access to your Postgres instance. You connect to pgAdmin through its public URL (e.g., pgadmin-yourorg.fly.dev) and from there, connect to your Postgres app using its internal Fly address (e.g., your-postgres-app.internal:5432).

What works: - Browser-based — accessible from any device - Internal network access — no proxy or tunnel needed - Familiar pgAdmin interface with full feature set

What does not work:

Additional cost. Running pgAdmin as a Fly app requires at least a 256 MB RAM VM to function properly. On Fly.io's pricing, that is approximately $3-5/month depending on the machine type. You are paying for a server that exists solely to give you a database GUI.

You are managing another app. pgAdmin on Fly needs its own configuration, its own secrets, its own health monitoring. The Docker image needs periodic updates to patch security vulnerabilities. You need to configure authentication properly — if you leave the default credentials or misconfigure access, you have just created a public admin panel for your database. This is the same self-hosted phpMyAdmin problem repackaged.

Storage for pgAdmin state. pgAdmin stores its own configuration (saved servers, query history, preferences) in a local database. On Fly, VMs are ephemeral by default — if the VM restarts, you lose pgAdmin configuration unless you attach a persistent volume (additional $0.15/GB/month).

Shared credentials. If multiple team members use the pgAdmin deployment, they either share the admin credentials (bad practice) or you configure LDAP/OAuth (more complexity). There is no simple multi-user setup.

Method 3: Browser-based GUI with DBEverywhere

DBEverywhere provides hosted phpMyAdmin and Adminer as a service. For PostgreSQL databases like Fly.io Postgres, it connects through Adminer. The key difference from the previous two methods: DBEverywhere connects from outside Fly's network, which means your Postgres database needs to be reachable from a known external IP.

There are two ways to make this work:

Option A: Allocate a public IP to your Fly Postgres app.

fly ips allocate-v4 --shared -a your-postgres-app

Then add a service in your fly.toml that exposes port 5432:

[[services]]
  internal_port = 5432
  protocol = "tcp"

  [[services.ports]]
    port = 5432

With this configuration, your Postgres instance is reachable at your-postgres-app.fly.dev:5432. You can then restrict access using Fly's fly ips list and your Postgres pg_hba.conf to only allow connections from DBEverywhere's static IP.

Option B: Use DBEverywhere's SSH tunnel (paid tier).

If you do not want to expose your Postgres port publicly, DBEverywhere's paid tier ($5/month) supports SSH tunnel connections. You create a small Fly app that runs an SSH server, configure it as a bastion host, and DBEverywhere tunnels through it to reach your private Postgres instance. This keeps your database fully private while enabling browser-based GUI access.

Comparison: all three approaches

Factor flyctl proxy + desktop client pgAdmin on Fly DBEverywhere
Setup time 10-15 min per developer 30-60 min 5-10 min (one-time)
Monthly cost Free $3-5/mo (Fly VM) Free / $5/mo
Requires CLI tools Yes (flyctl + desktop client) No (browser) No (browser)
Works on any device No Yes Yes
Maintenance None Update pgAdmin image, manage secrets None
Multi-user access Each user sets up independently Shared instance (credential sharing) Each user has own account
Database stays private Yes Yes (internal network) Option A: partial. Option B: yes
Persistent access No (proxy must be running) Yes (always-on app) Yes (connect anytime)

For solo developers on their primary machine, flyctl proxy works fine. For teams, or for developers who need access from multiple devices, the browser-based approaches (pgAdmin on Fly or DBEverywhere) are more practical. DBEverywhere has the advantage of zero infrastructure to manage — you are not adding another Fly app to your deployment.

Step-by-step: Connecting DBEverywhere to Fly.io Postgres

Here is the full process for Option A (public IP with restricted access):

Step 1: Allocate a public IP for your Fly Postgres app.

fly ips allocate-v4 --shared -a your-postgres-app

This assigns a shared IPv4 address. Run fly ips list -a your-postgres-app to see the allocated IP.

Step 2: Expose the Postgres port in fly.toml.

Add a service block for port 5432 in your Fly Postgres app's fly.toml:

[[services]]
  internal_port = 5432
  protocol = "tcp"

  [[services.ports]]
    port = 5432

Deploy the change: fly deploy -a your-postgres-app.

Step 3: Restrict access in pg_hba.conf.

Connect via flyctl proxy one last time to configure pg_hba.conf to only allow connections from DBEverywhere's static IP:

# Allow DBEverywhere's static IP
hostssl all all <DBEverywhere-IP>/32 scram-sha-256

# Allow Fly internal network
hostssl all all fdaa::/16 scram-sha-256

Reload PostgreSQL for the changes to take effect:

SELECT pg_reload_conf();

Step 4: Get your Postgres credentials.

Your Fly Postgres credentials were shown when you first created the cluster. If you have lost them, you can retrieve the connection string:

fly postgres connect -a your-postgres-app

Or check your app's secrets:

fly secrets list -a your-application-app

Your application typically has a DATABASE_URL secret containing the full connection string.

Step 5: Connect through DBEverywhere.

  1. Go to dbeverywhere.com and sign up.
  2. Click Connect and select PostgreSQL.
  3. Enter your Fly Postgres connection details:
  4. Host: your-postgres-app.fly.dev
  5. Port: 5432
  6. Username: postgres (or your custom user)
  7. Password: your Postgres password
  8. Database: your database name
  9. Enable SSL/TLS.
  10. Click Connect.

You now have a full Adminer interface for your Fly.io Postgres database — table browsing, data editing, query execution, and data export from any browser.

Fly.io Postgres is not managed — why that matters

Fly.io is explicit about this: their Postgres offering is not a managed database. The Fly.io Postgres documentation states: "Fly Postgres is not managed Postgres." This distinction matters for database management tooling in two ways.

You are responsible for backups. Fly does not automatically back up your Postgres data. You need to configure pg_dump schedules, WAL archiving, or point-in-time recovery yourself. A GUI tool that supports data export (like Adminer through DBEverywhere) can serve as a quick manual backup method — export a SQL dump of critical tables before making changes. This is not a substitute for automated backups, but it is a safety net that the MySQL CLI alone does not provide easily.

You are responsible for version upgrades. When a new PostgreSQL version ships security patches, you need to upgrade your Fly Postgres app yourself. This typically involves creating a new Postgres app with the updated version and migrating data. Having a GUI makes it easier to verify that data migrated correctly — compare row counts, spot-check critical tables, and verify schema integrity.

Failover is limited. Fly does offer multi-region read replicas for Postgres, but automatic failover requires configuration. If your primary Postgres VM goes down, you need to promote a replica manually. A GUI tool gives you quick visibility into database state during failover events — check replication lag, verify data consistency, and confirm the promoted replica has the expected data.

For teams that need truly managed PostgreSQL with built-in backups, failover, and a web GUI, Neon or a traditional managed service may be a better fit. For teams that want the flexibility and pricing of Fly.io but miss having a database GUI, DBEverywhere bridges that gap.

FAQ

Can I use DBEverywhere's free tier with Fly.io Postgres?

Yes. The free tier gives you 5 sessions per month with a 20-minute timeout per session. For occasional database checks — verifying a deployment, looking up a record, running a quick query — this is enough. Each session connects for up to 20 minutes, and you can start a new session for a different database or the same one. The paid tier ($5/month) provides unlimited sessions with an 8-hour timeout.

Is it safe to expose my Fly Postgres port publicly?

Exposing port 5432 to the entire internet is not recommended. But restricting access to a single IP address through pg_hba.conf limits the attack surface to one known endpoint. Combined with strong Postgres credentials (use scram-sha-256 authentication) and SSL/TLS encryption, this is comparable in security to the flyctl proxy approach — the connection is encrypted, authenticated, and restricted. If you want zero public exposure, use DBEverywhere's SSH tunnel option on the paid tier.

Does DBEverywhere work with Fly.io MySQL (PlanetScale partnership)?

Fly.io previously partnered with PlanetScale to offer MySQL. That partnership has evolved, and Fly now focuses on PostgreSQL as its primary database offering. If you are running MySQL on Fly (either through a custom Docker image or a legacy PlanetScale integration), DBEverywhere connects to it through phpMyAdmin. See our PlanetScale GUI guide for PlanetScale-specific details.

Can multiple team members use DBEverywhere to access the same Fly Postgres database?

Yes. Each team member creates their own DBEverywhere account and connects using the same Postgres credentials (or ideally, separate Postgres users with appropriate permissions). There is no shared state between accounts — each person's sessions are isolated. On the paid tier, each user can save their own connection details. This is simpler than sharing a pgAdmin deployment where credential management becomes a security concern.

What about Fly.io Supabase integration?

Fly.io announced a partnership with Supabase for managed PostgreSQL. If you are using Supabase on Fly, you get Supabase's built-in table editor and SQL editor — which is a significantly better database management experience than raw Fly Postgres. However, Supabase's pricing starts higher than running Fly Postgres directly, and you are tied to Supabase's platform layer on top of PostgreSQL.

Conclusion

Fly.io builds excellent application hosting infrastructure. What it does not build is a Fly.io Postgres GUI. The community forum thread is right — interacting with Postgres on Fly.io is harder than it should be. The flyctl proxy workflow requires CLI tools on every device. Deploying pgAdmin as a Fly app costs money and adds maintenance. Neither option gives you quick, any-device access to your data.

DBEverywhere cuts through the networking complexity. Expose your Fly Postgres port to one static IP (or use an SSH tunnel on the paid tier), and you get a full Adminer interface from any browser. No flyctl required, no pgAdmin deployment to maintain, no desktop client to install.

The free tier handles occasional database checks with 5 sessions per month. The paid tier at $5/month covers daily use with unlimited sessions, 8-hour timeouts, and saved connections so you do not re-enter credentials each time you need to check your data.

Fly.io makes deploying apps easy. Interacting with the database behind those apps should be just as easy.

Try DBEverywhere free — connect to your Fly.io Postgres database in 60 seconds

Try DBEverywhere Free

Access your database from any browser. No installation, no Docker, no SSH tunnels.

Get Started