Databases
Managed databases are enabled for a limited group. Contact support to request access.
This page covers creating a database, connecting it to a service, and running it day to day. For what a managed database is and how to pick a tier, see Databases.
How managed databases work
A database belongs to a Project. Every Service in that Project can connect to it; services in other projects can't. Separate environments are separate projects, so each environment gets its own isolated database.
On the shared tier your database runs on a cluster Forte operates. The storage is yours alone. The compute is shared with other databases on the same cluster.
Your code reaches the database over a TLS-encrypted endpoint using sslmode=require. Most drivers handle this on their own when the connection string asks for it.
Create a database
Use the console or the CLI. The SDKs don't support database management yet.
From the console:
- Open the Databases tab in your project.
- Choose New database.
- Pick PostgreSQL as the engine and Shared as the tier.
- Name the database. Names take letters, numbers, hyphens, and underscores, and run 3 to 30 characters.
- Choose a storage size.
- Create it. The database is ready in under 30 seconds.
From the CLI:
forte databases create --name orders-db --storage 25Omit any argument and the CLI prompts for it. forte databases list and forte databases get show status and storage; forte databases update --storage 50 resizes.
Choose a storage size
Storage is the only size you pick on the shared tier. Compute is shared across the cluster, so there's no CPU or memory setting.
| Preset | Storage | Suits |
|---|---|---|
| Hobby | 10 GB | Prototyping and side projects |
| Standard | 25 GB | Production apps with steady load |
| Performance | 100 GB | High-throughput workloads |
You can set any custom size from 10 GB to 250 GB instead.
Resizing is online. Pick a new size in the database's settings and it applies right away: no downtime, no restart. You can shrink a database as well as grow it, as long as the new size still exceeds the data it already holds.
Creating a database larger than 10 GB requires a verified billing method. Storage bills at the same rate whichever size you choose: see Pricing and quotas.
Connect a database to a service
Open the database, choose Connect to a service, and pick the service. You then choose the environment variable names your code already reads: either a single connection string (DATABASE_URL by default) or discrete values for host, port, database, username and password. Forte suggests the names your framework expects.
The CLI does the same thing:
# Prompts for the variable name, pre-filled with DATABASE_URL
forte databases connections add
# Or name the variables outright
forte databases connections add --service <serviceId> \
--host-var PGHOST --port-var PGPORT --database-var PGDATABASE \
--username-var PGUSER --password-var PGPASSWORDOn confirm, Forte:
- Creates a Postgres role dedicated to that service, with access to this database only.
- Sets the variables you mapped on the service.
- Redeploys the service so they reach the running container.
The password is generated by Forte and never shown: not in the console, not in the API response, and not in the service's own environment variable list. Your code reads it from the environment like any other variable:
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 2 });Changing the mapped names redeploys with the new names. Disconnecting reverses everything: the role is dropped, the variables are removed, and the service redeploys without them.
A service's own environment variables and secrets can't use a name a connected database owns, and vice versa: whichever you try second is rejected rather than silently overriding the other.
For a complete working app, see the Next.js + Node example, which stores per-user records in a connected Postgres database.
Manage database users
Connecting a service creates its role for you. Create a database user yourself when something outside Forte needs access: a migration tool, a SQL client, or an analytics job.
On the Users tab you can:
- Create a user. Forte generates the password and shows it once. Copy it before closing the dialog; Forte can't show it again.
- Rotate a password. The old password stops working immediately, so anything still using it fails until you update it. The new password is shown once.
- Delete a user. Existing connections for that user are closed.
Each database holds up to 25 users.
Connect a SQL client
The database's overview page shows the host, port, and database name. Take the password from the user you created on the Users tab: it's shown once, when you create the user or rotate its password.
Point any Postgres client at those values:
postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslmode=requireThree things to get right:
- Use the port shown in the console, not 5432. Connections arrive at a pooler, not at Postgres directly.
- TLS is required. Set SSL mode to
require(or stricter). A plaintext connection is refused. - Turn off server-side prepared statements. The endpoint pools per transaction, so prepared statements don't survive between queries. In DBeaver and DataGrip this is a driver property:
prepareThreshold=0on the JDBC URL does it.psqlneeds nothing.
Session state doesn't carry across queries either, so a client that sets a search path on connect won't keep it. Qualify your table names, or set the search path on the role itself with ALTER ROLE ... SET search_path.
Connection limits
Each database user gets 5 concurrent connections. That budget covers every client using that user at once, including every running instance of a service, since all instances share one role.
Size your connection pool accordingly. A service on 2 provisioned instances should cap its pool at 2 connections per instance, not 5.
Connections pass through a transaction-mode pooler, which reuses a server connection per transaction rather than per session. Session-scoped features don't survive that: avoid LISTEN/NOTIFY, session-level advisory locks, SET statements meant to persist across queries, and server-side prepared statements. Most drivers have a flag to turn off prepared statements: set it if your queries fail with prepared-statement errors.
Query limits
Forte applies limits to every database user so one query can't take the cluster down.
| Setting | Value | What it does |
|---|---|---|
statement_timeout | 30 seconds | Cancels a single query that runs longer. |
transaction_timeout | 5 minutes | Cancels a transaction open longer than this. |
idle_in_transaction_session_timeout | 60 seconds | Cancels a transaction left idle, releasing its locks. |
work_mem | 16 MB | Memory per sort or hash step before it spills to disk. |
temp_file_limit | 256 MB | The most temporary file space one query can use. |
| Parallel query | Off | Queries run on a single worker. |
Batch jobs and large migrations need to work within these. Split long-running work into smaller transactions.
Monitor a database
The Monitoring tab charts queries, average query time, rows read and written, connections, and active time, over the last hour, 24 hours, or 7 days. The connections chart draws the 5-connection limit as a reference line.
The slow-query list shows the queries taking the longest, so you can find the missing index before it costs you a timeout.
When storage runs out
Forte tracks how much of your provisioned storage the database uses and warns you before it fills:
- 80% full: Forte emails you.
- 95% full: Forte emails you again.
- 100% full: the database goes read-only. Queries still read; writes are rejected.
Resizing is the fastest fix and applies immediately. Because deleting data needs writes, a full database can't clean itself up: contact support for a temporary write window if you'd rather delete data than grow the database.
Database states
| State | What it means |
|---|---|
| Creating | Forte is provisioning the database. |
| Active | The database accepts reads and writes. |
| Read only | Writes are rejected, reads still work. Storage is full, or support set it. |
| Suspended | Connections are closed and refused. |
| Deleting | Forte is removing the database. |
| Failed | Provisioning failed. Contact support. |
Backups
Forte backs up every database once a day. To restore from a backup, contact support.
Delete a database
Disconnect every service first: Forte blocks the delete while any connection remains. Then open the database's settings, choose Delete, and type the database name to confirm.
Deleting a database destroys its data.
Limits
| Limit | Value |
|---|---|
| Databases per account | 5 (1 without a verified billing method) |
| Storage per database | 10 GB to 250 GB |
| Users per database | 25 |
| Services connected per database | 20 |
| Concurrent connections per user | 5 |
To raise a limit, email support@forteplatforms.com.
Next steps
- Pricing and quotas: database rates and worked example costs.
- Deploying Services: deploy the service that connects to your database.