Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
Platform as a Service (PaaS)

How do I create a Fly.io Managed Postgres database and attach it to my app privately?

Fly.io7 min read

Most apps don’t die because of CPU. They die because of the database. On Fly.io, “Managed” Postgres gives you a production-grade cluster—replication, failover, snapshots—without making you turn into a full-time DBA, and private networking keeps your app talking to Postgres over an internal WireGuard network instead of the public internet.

Quick Answer: Use fly postgres create to spin up a Fly Postgres (unmanaged-but-batteries-included) cluster in the same organization as your app, then fly postgres attach to wire it up over private networking. Your app gets a private DATABASE_URL and TLS config; your database never needs a public port.


The Quick Overview

  • What It Is: A Fly Postgres (unmanaged) cluster created and managed via fly postgres commands, with replication, failover, snapshots, and private networking wired in by default.
  • Who It Is For: Developers who want production-capable Postgres on Fly.io with sane defaults, private app-to-DB traffic, and flyctl-level control—but who are okay owning backups and upgrades as part of their app.
  • Core Problem Solved: Running Postgres close to your app with low latency and no public exposure, without hand-building clusters, DNS, health checks, or private networking by hand.

Note: Fly Postgres is intentionally not a fully abstract “managed service.” It’s a Fly app with strong defaults and sugar on top. You still get to be an adult about backups, upgrades, and migrations.


How It Works

When you create “Managed” Postgres on Fly.io, you’re really creating a special Fly app based on the open-source fly-apps/postgres-flex image. flyctl wraps this in fly postgres commands so you can:

  • Spin up a clustered Postgres app, usually in a “High Availability” 3-node configuration.
  • Put it on the same private WireGuard network as your application.
  • Attach it to one or more apps, auto-injecting DATABASE_URL and TLS env vars.
  • Let Fly Proxy route traffic from your app containers to the Postgres Machines privately.

At runtime, your app connects to Postgres over the private network using the injected URL. No public IPs required, no random internet clients knocking on your database port.

1. Create the Postgres Cluster

From any directory (you don’t have to be in your app folder):

fly postgres create \
  --name my-db \
  --organization my-org \
  --region iad

During the interactive prompts you’ll typically:

  • Pick a High Availability preset for production (3-node cluster).
  • Confirm the organization that matches your app.
  • Choose the region closest to your app’s primary users.

This creates a Fly app named my-db with Postgres Machines, volumes, health checks, and scheduling already configured.

2. Put the DB Near Your App

If your app already exists, confirm its primary region:

fly status -a my-app

If the app and DB are in different regions and latency matters, either:

  • Recreate the DB in the same region as the app, or
  • Move app Machines closer to the DB with fly scale count and fly regions add/remove.

Think: app and DB should usually share a region for write-heavy workloads.

3. Attach the Database Privately to Your App

Now wire your app to the Postgres cluster:

fly postgres attach my-db \
  --app my-app

This does a few important things:

  • Creates a database user and database for my-app.
  • Injects DATABASE_URL (and related vars) into my-app as secrets.
  • Ensures the connection string uses the private network address, not a public IP.

Your app code just reads DATABASE_URL (via env) and connects as usual. Under the hood, connections never leave the private Fly network.


Features & Benefits Breakdown

Core FeatureWhat It DoesPrimary Benefit
fly postgres bootstrapCreates a Postgres Fly app with replication, failover, and snapshots wired inProduction-ready Postgres without hand-rolling clusters
Private WireGuard networkingPuts app and DB on the same private network; no public listener requiredKeeps DB traffic off the public internet, reduces attack surface
attach-based env injectionGenerates app-specific user/db and sets DATABASE_URL secretsZero manual string-copying, fewer misconfigurations

Ideal Use Cases

  • Best for production web apps needing a “managed enough” Postgres: Because it gives you HA, snapshots, and private networking out of the box, while letting you upgrade and tune like a real Postgres instance when you need it.
  • Best for staging and preview environments: Because you can spin up smaller clusters or single-node setups, attach to ephemeral apps, and keep everything private without juggling shared dev databases.

Limitations & Considerations

  • Not a fully abstract managed service: You still own schema migrations, major version upgrades, and retention decisions. Read why Fly Postgres isn’t “managed DBaaS” before betting the company on it.
  • Organization & network boundaries matter: Your app and DB must live in the same organization and on the same private network to attach. Cross-org or cross-network database sharing isn’t a thing; design your org layout accordingly.

Pricing & Plans

You don’t pay a separate “managed database” line item. You pay for the underlying Fly primitives:

  • CPU and RAM for Postgres Machines (billed per second).
  • NVMe volumes for the cluster’s data.
  • Object storage if you use external backups (via Tigris or similar).

The preset “High Availability” clusters choose reasonable sizes; you can adjust them later with fly scale vm and fly volumes extend. Lower environments can run cheaper, single-node setups if you’re okay trading away failover.

  • Standard HA Cluster: Best for teams running production workloads that need replication, failover, and daily snapshots with minimal babysitting.
  • Single-Node or Small Cluster: Best for dev/staging environments and cost-sensitive projects where occasional downtime is acceptable.

Check the current pricing page on Fly.io for exact per-CPU and per-GB volume costs.


Frequently Asked Questions

Do I have to expose my Postgres database publicly?

Short Answer: No. You should run it entirely on the private Fly network.

Details: When you create and attach a Fly Postgres cluster, your app uses a private address on Fly’s WireGuard-backed network. You don’t need to assign a public IP or open port 5432 to the world. If you do add a public IP (for external tools, BI, etc.), lock it down with proper auth and firewall rules; the safe default is “private only.”


Can I share one Postgres cluster between multiple Fly apps?

Short Answer: Yes, via multiple attach calls, but each app gets its own credentials.

Details: You can run:

fly postgres attach my-db --app app-one
fly postgres attach my-db --app app-two

Each attach creates a separate user and database and injects env vars into the target app. All of this stays on the same private network as long as the apps live in the same organization and network. Operationally, you’re now sharing one cluster, so size and monitor it accordingly—noisy apps can impact neighbors.


Summary

Creating a “Managed” Postgres database on Fly.io really means spinning up a purpose-built Fly app for Postgres, then letting fly postgres wire in the private networking, HA, and secrets so your app just sees DATABASE_URL. You get replication, failover, and snapshots with minimal configuration, traffic stays on a private WireGuard mesh instead of the public internet, and you only pay for Machines and storage as they run.

If you’re comfortable owning your database like a grown-up but don’t want to assemble clustering, routing, and private networking from scratch, this is the sweet spot: Postgres that acts like part of your app, not a separate cloud religion.


Next Step

Get Started