frontback / databases / postgres

Managed Postgres

Real Postgres, created per project and linked to the services that need it. Credentials arrive as environment variables, nothing is exposed to the internet, and we run the server.

What you get

A database is a project-level resource, not a hidden extra on a service. You create one, you link it to the services that should reach it, and you name the link. That name becomes the prefix of the environment variables the service receives, so a link called APP_DB arrives as APP_DB_URL with everything the driver needs already in it.

Nothing is injected behind your back and nothing listens on the public internet. There is no implicit database and no magic DATABASE_URL, because a variable you did not ask for is a variable you cannot reason about.

main.ts
import postgres from "npm:postgres";

// APP_DB is the name you gave the link; the URL is already complete.
const sql = postgres(Deno.env.get("APP_DB_URL")!);

export default {
  async fetch() {
    const rows = await sql`select count(*)::int as n from visits`;
    return Response.json(rows[0]);
  },
};

It is ordinary Postgres, so an ordinary driver connects to it: pg, postgres.js, Prisma, Drizzle, psycopg, ActiveRecord, whatever your language already uses. Migrations run the way they always did.

When Postgres is the right answer

Two managed engines is one more than most people need, so here is the honest split rather than a matrix.

Reach for Postgres
Extensions (PostGIS, pgvector, full text), types your schema actually leans on, concurrent writers, analytical queries, or a team that already knows how to operate one.
Reach for libsql
A service that sleeps between requests, a workload that reads far more than it writes, and anything where you want to fork the whole database to rehearse a migration.
Use both
Nothing stops you. They are separate resources in the same project, and a service can be linked to both under two names.

What it is good at, and what it is not

  • It is real Postgres, so extensions, exact SQL and every tool you already own behave the way they do on your machine.
  • It is private by default: a linked service reaches it over the internal network, and there is no public port for anyone to scan.
  • Credentials are handed to the service as environment variables and rotate with the link, so nothing lives in your repository.
  • It is a project resource, so staging and production can each hold their own, and a service reaches only what you linked.
  • Postgres wants connections, and a service that scales to zero opens and closes them constantly. For that shape libsql over HTTP is the calmer answer.
  • One instance. Read replicas, automatic failover and point-in-time recovery are not here yet, and we would rather say so than imply a cluster.
  • Storage is capped by your plan rather than elastic, so a database that grows without bound needs a plan that expects it.

What it costs

Databases are included in the plan rather than metered separately, and the count is shared across engines: a Postgres database and a libsql database both spend one of them.

  • Free, €010 databases, 50 MB each
  • Pro, €19 a month10 databases, 5 GB each
  • Business, €99 a month50 databases, 20 GB each

Questions people ask about it

You link the database to the service and name the link. The name becomes the environment variable prefix, so <code>APP_DB</code> gives you <code>APP_DB_URL</code>. Unlink it and the variable is gone on the next deploy.

No. Linked services reach it over the internal network, and a link cannot cross into another project. Ask if you need an external connection for a migration tool and we will tell you how that works today.

That is most of the reason Postgres is here. Tell us which one you need; the common ones are enabled and the list grows with the asking rather than with a support ticket.

Snapshots are ours to run. Point-in-time recovery is not here yet, so if your business depends on rewinding to an exact second, plan your own dumps as well until it is.

If your schema needs Postgres, use Postgres. If your service sleeps between requests and reads more than it writes, libsql over HTTP is a better fit, and forking it to rehearse a migration is a click. Using both in one project is normal.

On our own machines in the EU, the same ones your services run on, so a query is a short hop rather than a trip across the internet. EU hosting is the default on every plan, not an add-on.

The other two

Go beyond what seems possible.