Skip to content

PostgreSQL

Managed PostgreSQL 15, 16, and 17 with automated backups, point-in-time recovery, and zero-config internal connectivity.

From + Service → Databases, add PostgreSQL. Pick version (15, 16, or 17), disk size, and plan. It appears on the canvas in seconds.

Open another service, go to Variables, and attach the database. DATABASE_URL is injected as a secret. You can also wire it in stackblaze.yaml with fromDatabase.

StackBlaze exposes two connection strings per database: an internal one for services in the same project, and an external one for local tooling like Postico or TablePlus.

Services in the same environment talk over the private network using the database service name. Traffic stays inside the environment.

Connection string (internal)
postgresql://user:password@[service-name]:5432/dbname

The external connection string is available in the dashboard under Settings → Connection. It uses SSL and routes traffic through our secure proxy. Use this for GUI clients like TablePlus, Postico, or DBeaver, not for production app connections.

Connection string (external, SSL required)
postgresql://user:password@db.stackblaze.cloud:5432/dbname?sslmode=require

The safest pattern is to run migrations as a pre-deploy command so they complete before new traffic reaches your updated service. Configure this under Settings → Deploy → Pre-deploy command.

Pre-deploy command
npx prisma migrate deploy
Pre-deploy command
npm run migrate
Pre-deploy command
python manage.py migrate

Queue a build after your own migrate job, or set a pre-deploy command on the app so StackBlaze runs it with the same env as the workload (including DATABASE_URL). There is no stackblaze run CLI.

On Pro and Enterprise plans, StackBlaze continuously archives WAL (Write-Ahead Log) segments to object storage alongside periodic base backups. This lets you restore your database to any moment within your plan’s retention window, not just the last daily snapshot.

To initiate a PITR restore, navigate to your database in the dashboard, click Backups → Restore to point in time, select a timestamp, and choose whether to restore in-place or to a new instance.

Plan PITR Retention window
Free No
Starter No 3 days (snapshots)
Pro Yes 7 days
Enterprise Yes 30 days

All plans include automated daily snapshots taken during off-peak hours (typically 02:00–04:00 UTC). Backups are encrypted at rest and stored separately from your primary data.

To restore from a snapshot, go to Backups in the database dashboard, select the snapshot, and click Restore. You can restore to a new instance without affecting the running database.

The following popular extensions are available on all plans and can be enabled without any configuration:

Extension Use case
postgis Geospatial data and queries
pgvector Vector similarity search for AI/ML workloads
pg_trgm Fuzzy text search using trigrams
uuid-ossp UUID generation functions
pg_stat_statements Query performance tracking
btree_gin GIN indexes for B-tree operators
hstore Key-value store within a column
citext Case-insensitive text type
Enable an extension
CREATE EXTENSION IF NOT EXISTS pgvector;
CREATE EXTENSION IF NOT EXISTS postgis;

To increase CPU or memory, upgrade the database plan from the dashboard under Settings → Plan. StackBlaze performs a rolling StatefulSet update with a brief connection interruption (typically under 30 seconds). Schedule vertical scaling during off-peak hours.

Read replicas are available on Enterprise plans. They use PostgreSQL streaming replication and are typically under 1 second behind the primary. Connect read-heavy workloads (analytics queries, reporting) to the replica connection string to reduce load on the primary.

prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
db.ts
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
const client = postgres(process.env.DATABASE_URL!)
export const db = drizzle(client)
database.py
from sqlalchemy import create_engine
engine = create_engine(
os.environ["DATABASE_URL"],
pool_size=5,
max_overflow=10,
pool_pre_ping=True,
)