25. Direct Postgres connection (Team & Legal Team)
When the SDK / REST / edge-functions / SQL editor / MCP aren't enough — because your stack expects a raw postgres:// URL.
Why this exists
On Free and Pro, every project shares one Postgres cluster with per-tenant schema isolation + RLS.
We don't hand out direct connection strings on those tiers — the isolation model relies on you
going through our authenticated surface (SDK, REST, MCP, edge functions with ctx.db.sql, the console SQL editor).
That covers most application code — but not tools that want to own the Postgres connection themselves:
- Payload CMS — Postgres adapter requires
DATABASE_URL - Prisma — same
- Drizzle — same
- Directus, Strapi (Postgres backend) — same
- Migration runners: Flyway, Liquibase,
node-pg-migrate,sqlx - Ad-hoc
psqlfrom your laptop
What Team unlocks
Every Team-tier project (and Legal-Team) gets its own dedicated Postgres instance in Scaleway fr-par — no shared cluster, no cross-tenant noise. That instance has its own connection string, exposed at Project → Database → Connection in the console.
Two roles: read-only (default — safe for analytics, debugging, most reads) and read/write (owner role — for migrations + writes). Both work with any Postgres client.
Right after a Team database is created, the read-only role may still be provisioning for a few minutes:
the console shows "Read-only role still provisioning", and the API
(GET …/connection?role=readonly) answers 409 with "code": "readonly_pending" and no credential —
it never hands out the read/write login instead.
team.connection.url_viewed). If a URL leaks, hit
the Rotate password button — the old URL stops working within seconds.Client examples
Payload CMS
// payload.config.ts
import { postgresAdapter } from '@payloadcms/db-postgres';
export default buildConfig({
db: postgresAdapter({
pool: { connectionString: process.env.DATABASE_URL },
}),
});Prisma
// schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}Drizzle
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client);psql
psql "$DATABASE_URL"Connection limits
Your instance allows 100 connections (Scaleway's default), of which about 95 are usable — a few are reserved for Scaleway's own maintenance. They are shared by your own clients and by Eurobase itself: the SDK, the console, edge functions, scheduled jobs and background jobs use up to about 50 during a deploy or an export, fewer otherwise. The read-only role is capped at 10 connections.
Leave that headroom free — if your app opens every remaining connection, your own SDK and console traffic start failing. Size your client's pool accordingly (a total of about 40 across all your processes):
- Prisma: add
?connection_limit=10to the URL (per process). - node-postgres / Payload:
pool: { connectionString, max: 10 }. - postgres.js / Drizzle:
postgres(url, { max: 10 }). - Serverless (many short-lived instances): keep the per-instance pool at 1–2, or put a pooler in front.
Free / Pro alternatives
If you don't need direct connection, all Free/Pro projects can still work with tools that speak our SDK / REST — see chapters 4, 10, 23. When you're ready for a stack that wants raw Postgres, upgrade to Team from Project → Settings.