Databases
A project can have one managed PostgreSQL database. Vinssi provisions it in Helsinki next to your app, injects DATABASE_URL into every build and deployment, backs it up, and bills it on the project's subscription. Prices are in euros per month and exclude VAT.
Tiers
| Tier | Price | Instance | Storage | Connections | Backups |
|---|---|---|---|---|---|
| Postgres Lite | €5 / month | Shared pool, no dedicated CPU or memory | 1 GB | 5 | Nightly, kept 7 days |
| Postgres Starter | €12 / month | Dedicated, 1 GB RAM | 10 GB | 50 | Point-in-time recovery, 3 days |
| Postgres Standard | €45 / month | Dedicated, 2 GB RAM | 25 GB | 50 | Point-in-time recovery, 3 days |
| Postgres Plus | €89 / month | Dedicated, 4 GB RAM | 50 GB | 100 | Point-in-time recovery, 3 days |
Storage and connection counts are hard limits. Lite is a logical database on a Postgres instance Vinssi runs for many projects; the dedicated tiers are a Postgres instance of their own. All tiers are PostgreSQL with TLS required.
Adding a database
In the dashboard, open the project's Settings → Database, pick a tier and confirm. The charge is added to the workspace subscription immediately, prorated like a plan change.
From the CLI:
vinssi db create <project> --plan lite
vinssi db status <project>
Lite is ready in seconds. A dedicated database takes 5 to 10 minutes to provision; the status shows provisioning until then. Once it is running, Vinssi redeploys the project automatically using the same build artifact, so the app starts with DATABASE_URL set without a rebuild.
A project needs an active plan and must not be scheduled for deletion.
How DATABASE_URL reaches your app
The connection string is not an environment variable you manage. Vinssi holds it encrypted and injects it as DATABASE_URL:
- During the build, so
prisma generate, migrations and anything else that reads the URL at build time work. - At runtime, in the app container.
The Settings → Variables page shows it as a read-only row provided by the managed database. If you also defined a DATABASE_URL variable yourself, the managed value overrides it, and the page warns you about the conflict. Delete your own variable to avoid confusion.
The URL already includes sslmode=require. Do not store it anywhere else; use vinssi db url <project> when you need it, for example to run a migration from your machine through a tunnel of your own. Each reveal is written to the project's activity log.
Network
The database sits on a private network. Only the project's own app can reach it. There is no public endpoint, no IP allowlist to maintain, and no way to connect from another project or from outside Vinssi.
Connection limits and pool sizing
Every tier caps concurrent connections, and one app instance is the only client, so size your pool to the cap:
- Lite allows 5 connections. The injected URL carries
connection_limit=5, which Prisma honours. Thepgdriver ignores that parameter, so configure it yourself:new Pool({ connectionString: process.env.DATABASE_URL, max: 5 }). Drizzle and Kysely users onpgorpostgres.jsdo the same withmax: 5. - Starter and Standard allow 50, Plus allows 100. Leave headroom for migrations and one-off scripts; a pool of 10 to 20 is plenty for one instance.
Exceeding the cap makes new connections fail with too many connections for role, not queue.
Lite caveats
Lite is built for small apps and prototypes. Know what you give up:
- Shared instance. CPU and memory are shared with other Lite databases. Vinssi limits each database so no neighbour can take the instance down, but throughput is not guaranteed.
- Storage limit. 1 GB, measured nightly; the dashboard and
vinssi db statusshow current use. Treat 800 MB as the warning line. Once the database has been over 1 GB for 7 days it is suspended: connections are refused until it is back under the limit or you upgrade to a dedicated tier, which lifts the limit. Vinssi does not delete data to enforce the limit. - Statement timeout. Any statement running longer than 30 seconds is cancelled. Long migrations and analytical queries belong on a dedicated tier.
- Backups are nightly dumps, not point-in-time recovery. Restore is a support request in this version.
- No maintenance window of your own. Pool maintenance runs Sunday 03:00 UTC and affects every Lite database on it.
Upgrading
Change the tier under Settings → Database or with vinssi db upgrade <project> --plan <tier>. The database must be running.
Lite to a dedicated tier moves your data. Vinssi provisions the new instance first while Lite keeps serving, then pauses writes, copies the data, switches the connection string and redeploys. Expect writes to be paused for about 3 to 5 minutes; reads keep working throughout. The old Lite database is kept read-only for 7 days as a rollback source. If the copy fails, the original keeps serving and the database shows failed with a Retry action.
Between dedicated tiers the instance is resized in place. The hostname stays the same, so there is no redeploy, only a brief reconnect that any connection pool survives. The status shows resizing.
Downgrading
Downgrades between dedicated tiers take effect at the end of the current billing period, so you keep what you paid for. The pending plan and its date are shown in the dashboard and in vinssi db status. The resize refuses to run if your data exceeds the smaller tier's storage; free space before the date.
A dedicated database cannot move back to Lite: the data lives on a dedicated instance and the shared pool would not hold it safely. Create a new Lite database on another project and import your data if you need to.
Backups and recovery
- Dedicated tiers have point-in-time recovery for the last 3 days plus the provider's daily backups. Restores to a point in time are done by support on request in this version.
- Lite gets a nightly dump kept for 7 days. Restore is a support request.
Ask through cloud@vertics.co with the project id and the target time.
When billing lapses
If the subscription ends or payment stays past due:
- While payment is past due nothing changes; Stripe retries and the dashboard shows a warning.
- 7 days after the subscription ends, the database is suspended: a dedicated instance is powered off, a Lite database refuses connections. The data is intact.
- 30 days after suspension, the database is deleted. A Lite database leaves a final dump for 7 more days.
Reactivating the subscription during the suspension window powers the database back on and redeploys the app.
Deleting
Delete under Settings → Database, or:
vinssi db delete <project> --confirm
This cancels the charge, removes the instance or logical database, and stops injecting DATABASE_URL. The running app is not touched until the next deployment. A Lite database leaves a final dump kept for 7 days; a dedicated instance is gone with its backups. Take your own dump first if you want the data.
CLI
vinssi db plans [--json] List tiers and prices
vinssi db status <project> [--json] Status, plan, connection host, storage
vinssi db create <project> --plan <tier> tier: lite | starter | standard | plus
vinssi db upgrade <project> --plan <tier> Change tier; downgrades are scheduled
vinssi db url <project> Print DATABASE_URL only (logged)
vinssi db retry <project> Retry a failed provision or change
vinssi db delete <project> --confirm Delete the database and its data
db url prints nothing but the URL so it can be piped, for example psql "$(vinssi db url <project>)" from a host that can reach the private network. Every call is recorded in the project's activity log.