Databases
Create and manage PostgreSQL, MongoDB and Valkey databases.
ghayma db mode, ghayma db logs and --type valkey need CLI v0.13.0 or later.
ghayma db create
Create a new managed database in the current project (reads project_id
from .ghayma.json).
# PostgreSQL (default)
ghayma db create my-postgres
# MongoDB (needs tier m or larger; always a single-node replica set)
ghayma db create my-mongo --type mongodb
# Choose a compute tier, disk size, and backup schedule up front
ghayma db create my-postgres --tier s --disk-gb 20 --backup daily
# Connect it to the 'main' site as it is created
ghayma db create my-postgres --site main
# Valkey (Redis-compatible)
ghayma db create cache --type valkey --mode storeMongoDB starts at the m tier. The xs and s tiers are too small to run
MongoDB reliably (their 512 MiB ceiling can’t boot a replica set, so multi-document
transactions aren’t available there), so new MongoDB databases need tier m or
larger. PostgreSQL and Valkey run on every tier. MongoDB databases created on a smaller tier
before September 2026 were moved to m. MongoDB always runs as a single-node
replica set.
Valkey runs on every tier, xs included. It has no public access yet and its
disk cannot shrink. See the Valkey guide.
Options:
| Flag | Description | Default |
|---|---|---|
--type, -t | Database type: postgres, mongodb, valkey | postgres |
--mode | Valkey only: cache (evicts the least-recently-used keys when memory is full; snapshots only) or store (never evicts; a snapshot plus an append-only file synced every second). See Cache or store. | cache |
--tier | Compute tier, priced in points (e.g. xs, s, m, l). Interactive picker when omitted; server default if the catalog is unavailable. | picker / server default |
--disk-gb | Persistent disk in GB, priced in points. The volume is created at exactly this size. Server default (from the tier) when omitted. | server default |
--backup | Backup schedule: weekly, daily, sixhourly. Interactive picker when omitted; weekly if the catalog is unavailable. | picker / weekly |
--site | Connect the new database to this site (slug); repeat for several. See Connecting it to a site. | asked on a terminal |
--no-connect | Connect it to no site, without asking. | — |
MongoDB always runs as a single-node replica set (rs0), so multi-document
transactions work. In CLI v0.14.0 the --replica-set flag is hidden: it is
still accepted, and only --replica-set=false on a MongoDB is refused, before
anything is sent:
❌ MongoDB always runs as a single-node replica set: a standalone instance cannot give each app its own database user. Leave --replica-set out.Connecting it to a site
A new database is connected only to the sites you choose — even in a project
with a single site. Name them with --site, or pass --no-connect for none;
giving both is refused before anything is created, and so is a --site the
project doesn’t have (the error lists its sites).
ghayma db create my-postgres --site main --site adminWith neither flag, a terminal asks: one site gets
Connect database 'my-postgres' to site 'main'? (default Yes), several sites get
one question each (default No), and a project with no site yet is told that
ghayma deploy will offer to connect it. Without a terminal nothing is
connected, and the CLI prints the command that does it:
ℹ️ Not connected. Connect it with: ghayma connect database my-postgres --site mainAfter the create, each chosen site gets a line: 🔗 Connected to 'main', or
for a new PostgreSQL or Valkey database, which accepts connections a moment
after it is created, ⏳ Connecting to 'main' once it is ready to accept connections. A site
that could not be connected is named with the reason and a Retry with:
command. See How a service gets
connected.
Sizing and points
A database reserves points based on its tier, disk size, and backup schedule (see
Pricing by Service). Pass --tier,
--disk-gb, and --backup to set these non-interactively. If you pass none
of them, db create opens interactive pickers, each choice showing its points
cost:
Select a database tier
▸ xs — 0.25 vCPU / 256 MB · 2 pts
s — 0.5 vCPU / 512 MB · 4 pts
m — 1 vCPU / 1024 MB · 8 pts
Disk in GB — steps of 1 (blank for server default): 20
Select a backup schedule
▸ weekly — every 168h, keep 4 · +0 pts
daily — every 24h, keep 7 · +2 pts
sixhourly — every 6h, keep 28 · +6 ptsBefore the database is created, the CLI prints the points it will reserve:
This database will reserve 24 pts · 11 remaining afterThat line is for xs with 20 GB and daily backups on an otherwise empty Pro
project (35 points): 2 (tier) + 20 (disk, 1 point per GB) + 2 (daily backups,
two started 10 GB blocks) = 24, and 35 − 24 = 11. The same database on tier s
reserves 26.
The · N remaining after tail appears only when your project has a points budget
(it’s omitted for pay-as-you-go projects).
The tiers, disk steps, and points above come from the live catalog — the figures shown are only examples.
Interactive pickers: Ctrl-C cancels without creating anything — the CLI
prints ❌ Cancelled. and exits.
Output:
✅ Created postgres database 'my-postgres' (linked to project)
ID: <uuid>
Host: pg-mypostgres-a1b2c3d4-0.databases.svc.cluster.local
Port: 5432
Status: provisioning
⏳ Connecting to 'main' once it is ready to accept connectionsFor MongoDB, the output includes an additional Mode: line,
replica set (rs0) — transactions supported. The last line is the
connection to the site you chose.
For Valkey, the Mode: line says what the mode does, and a last line names the
variables connected apps receive:
✅ Created valkey database 'cache' (linked to project)
ID: <uuid>
Host: vk-cache-a1b2c3d4.pdb-<project-uuid>.svc.cluster.local
Port: 6379
Status: provisioning
Mode: store — never evicts; writes fail when memory is full. Snapshot plus append-only file every second.
Connected apps receive REDIS_URL and VALKEY_URL at runtime (not during builds).
⏳ Connecting to 'main' once it is ready to accept connectionsWithout --mode, the line reads
cache — evicts the least-recently-used keys when memory is full. Snapshots only.
These are refused before anything is sent:
$ ghayma db create r --type redis
❌ Redis is not offered. Create a Valkey database instead (--type valkey): it speaks the Redis protocol, so every Redis client works with it.
$ ghayma db create p --mode store
❌ --mode applies to Valkey only
$ ghayma db create v --type valkey --mode persist
❌ --mode must be cache or store, not "persist"A database belongs to one project for its whole life. It is created inside
the project in your .ghayma.json and cannot be moved to another one later.
Its connection variables — DATABASE_URL for PostgreSQL, MONGODB_URI
(alias MONGODB_URL) for MongoDB, REDIS_URL and VALKEY_URL for Valkey —
are derived for every site connected to it
(see ghayma db sites), so there is no
attach step to run afterwards. Connected apps pick them up straight away, and
every deploy derives them again — they are never stored env vars. A
Valkey’s variables reach the running app only, never a build. See
Automatically injected
variables.
ghayma db resize
Change a database’s compute tier, disk size, or backup schedule after it’s
created. Pass any combination of --tier, --disk-gb, and --backup — only the
options you set change.
# Move to a bigger compute tier
ghayma db resize my-postgres --tier m
# Grow the disk (online — the database stays up)
ghayma db resize my-postgres --disk-gb 40
# Shrink the disk (the database stops for about a minute)
ghayma db resize my-postgres --disk-gb 10
# Change the backup schedule
ghayma db resize my-postgres --backup sixhourlyOptions:
| Flag | Description |
|---|---|
--tier | New compute tier (e.g. xs, s, m, l) |
--disk-gb | New disk size in GB, at least 1. Larger grows the disk; smaller shrinks it if the data fits (a Valkey disk cannot shrink yet) |
--backup | New backup schedule: weekly, daily, sixhourly |
--no-wait | Return as soon as a disk change has started instead of waiting for it |
The platform makes a disk change in the background. By default the command
waits and shows its progress until the disk has its new size; with --no-wait
it returns once the change has started, and
ghayma db info shows Status: resizing until it is done. A
grow happens online: the database stays up, and the new size applies in about a
minute.
Notes:
- While a database is resizing, nothing else changes it until the resize
finishes:
db stop,db start,db deleteand any other resize are refused withresize_in_progress. Backup restores wait as well. - The disk changes only while the database runs. On a stopped database the
resize is refused with
database_not_running: runghayma db startfirst. - A size the platform has no storage for right now is refused with
storage_capacity: try a smaller size, or later. - Passing none of the flags does nothing:
❌ Nothing to change. Pass at least one of --tier, --disk-gb, --backup. - A new
--tieron a Valkey restarts it with the new memory limit: itsmaxmemoryis 70 % of the tier’s memory. See Memory and disk. - A smaller
--disk-gbon a Valkey is refused before any change is sent:❌ A Valkey disk can grow, but it cannot shrink yet. cache keeps its 2 GB disk.If the platform refuses it instead, the line stops aftercannot shrink yet. - A resize reserves or refunds only the difference in points against your
budget — see Points & Plans. The new disk size is
billed once the change is done. Check the current reservation any time with
ghayma points.
Shrinking, the progress wait and --no-wait need the CLI release that
carries them. An older CLI refuses a smaller --disk-gb itself
(❌ disk cannot shrink from 40 GB to 20 GB), and after a grow it returns at
once and prints the old disk size. If ghayma db resize --help does not list
--no-wait, update the CLI, or change the disk from the Dashboard.
Shrinking a disk
A PostgreSQL or MongoDB disk can shrink if what the database holds on disk fits
in 75 % of the new size. That counts the data plus the engine’s own files, such as
PostgreSQL’s WAL or MongoDB’s journal. The Dashboard shows the current on-disk
usage and the smallest size you can shrink to now; in the
API they are disk_used_bytes and min_disk_gb.
Asking for less changes nothing: the resize is refused with disk_too_small,
which names the smallest size that fits — see
Disk too small for the data.
The minimum disk is 1 GB. A Valkey disk cannot shrink yet.
A shrink stops the database for about a minute on a small database, longer on a large one, while its files are copied to the smaller disk. Apps cannot connect during that time, so pick a quiet moment. Everything else stays exactly as it was: credentials, users, connection strings and data. The smaller disk costs less from the moment the shrink is done.
If a shrink fails before the old disk is released, it is undone automatically and the database comes back on its original disk. If it stops later, the data is kept safe and support finishes the move.
ghayma db mode
Switch a Valkey database between its two modes: cache evicts the
least-recently-used keys when memory is full and keeps snapshots only; store
never evicts (writes fail when memory is full) and keeps a snapshot plus an
append-only file synced every second. See Cache or
store.
ghayma db mode <name> cache|storeThe cache database created above in store mode moves to
cache mode:
ghayma db mode cache cacheOutput:
⏳ Switching cache to cache mode. It restarts: a few seconds of downtime...
✅ cache is in cache mode: evicts the least-recently-used keys when memory is full. Snapshots only.The database restarts into the new mode: a few seconds of downtime. Moving
to cache first takes a fresh snapshot. Moving to store first writes the
append-only file, which takes longer on a large dataset, and ends with
✅ cache is in store mode: never evicts; writes fail when memory is full. Snapshot plus append-only file every second.
A database already in that mode is left alone:
ℹ️ cache is already in cache mode.Only a running Valkey can switch. The CLI checks the status first:
❌ cache is stopped, so its mode cannot change. Start it first: ghayma db start cache
❌ cache is provisioning, so its mode cannot change now. Try again once ghayma db info cache shows running.If the database was down for a moment when the switch reached it and runs again now, run the same command again:
❌ cache was not running a moment ago. Try again: ghayma db mode cache cacheOther refusals:
❌ The mode is cache or store, not "persist".
❌ my-postgres is a postgres database: only Valkey has a mode.Anything else the platform refuses prints ❌ Mode switch failed: followed by
its reason. If the append-only file or the snapshot cannot be written, the
database stays in its old mode.
ghayma db list
List all your databases.
ghayma db listOutput:
🗄️ Your databases (3):
my-postgres postgres running
my-mongo mongodb stopped
cache valkey runningColumns are name, type and status. A database in error shows why after
its status — for a Valkey that never became ready, what the platform saw:
jobs valkey error · CrashLoopBackOff: back-off restarting failed container exit 1ghayma db info
Show details about a database.
ghayma db info my-postgresOutput:
🗄️ Database: my-postgres
Type: postgres 16
Status: running
Host: pg-mypostgres-a1b2c3d4-0.databases.svc.cluster.local
Port: 5432
Database: db_mypostgres
Storage: 1024 MB
CPU: 500m
Memory: 512Mi
Project: <project-id>There is no Username: line: a database’s own login is never shown, and each
connected app has a credential of its own. For a Valkey, Database: gives way to
its mode and its users:
🗄️ Database: cache
Type: valkey 9.1
Status: running
Host: vk-cache-a1b2c3d4.pdb-<project-uuid>.svc.cluster.local
Port: 6379
Mode: store — never evicts; writes fail when memory is full. Snapshot plus append-only file every second.
Users: each connected app has its own user (REDIS_URL / VALKEY_URL)
Storage: 2048 MB
Disk used: 1.2 GB
CPU: 500m
Memory: 512Mi
Project: <project-id>A Valkey’s Disk used: line never names a smallest disk, because its disk
cannot shrink yet. A Valkey in error shows the reason on its status line:
Status: error · <reason>.
ghayma db logs
Show the last lines of a database’s engine log. Every engine has one: PostgreSQL, MongoDB and Valkey.
ghayma db logs <name> [-n <lines>] [-f]# The last 200 lines
ghayma db logs cache
# The last 500, then keep printing new lines
ghayma db logs cache -n 500 -fOptions:
| Flag | Description | Default |
|---|---|---|
-n, --lines | Number of lines to show, 1-1000 | 200 |
-f, --follow | Keep printing new lines until Ctrl-C (up to 10 minutes) | — |
Output: the log as the platform streams it, each line prefixed with its timestamp:
2026-10-08T09:12:22.108356960Z 1:M 08 Oct 2026 09:12:22.108 * Valkey is starting
2026-10-08T09:12:22.139Z 1:M 08 Oct 2026 09:12:22.139 * Ready to accept connections tcpA follow ends after 10 minutes, or when the database restarts. Ctrl-C ends
it quietly. When the platform ends it, the CLI says so on stderr, so
ghayma db logs cache -f > cache.log keeps only log lines. The blank lines a
follow uses to keep the connection open are never printed.
ℹ️ The stream ended (the platform ends a follow after 10 minutes, or when the database restarts). Run the command again to keep following.A database with no running engine has no log to show:
❌ cache is stopped, so it has no running log. Start it with: ghayma db start cache
❌ cache did not start, so it has no log yet. See why: ghayma db info cache
❌ cache is not running yet, so it has no log. Check: ghayma db info cacheThe first is a stopped database, the second one in error, the third one
still starting. Reading the log needs the project write role. Any other
refusal prints ❌ Could not read the log: followed by the platform’s reason.
ghayma db credentials
Show where a database answers and which apps receive its credentials — without any secret.
ghayma db credentials my-postgresOutput:
🔌 Connection details for 'my-postgres' (postgres)
Host: pg-mypostgres-a1b2c3d4-0.databases.svc.cluster.local
Port: 5432
Database: db_mypostgres
Connected sites and the variables they receive:
main connect DATABASE_URL, DATABASE_URL_MY_POSTGRES
admin read-only DATABASE_URL, DATABASE_URL_MY_POSTGRES
No password is shown: each site has its own credential, delivered in these variables.
From your laptop: ghayma connect --local
From outside Ghayma: ghayma access add database my-postgres --name <principal>Host is the in-cluster hostname, the one a deployed app uses. Each
connected site comes with its level
and the exact variable names it receives; the values hold that site’s own
credential, and ghayma env pull writes them
for one site. A database no site is connected to says so in place of the list:
Not connected to any site. Connect one with: ghayma connect database my-postgres --site <slug>A database that belongs to no project prints
❌ Database 'my-postgres' belongs to no project.
A database’s own login is never shown, to anyone. Every app connected
to it holds a credential of its own (c_ followed by eight characters) in its
DATABASE_URL or MONGODB_URI — see Each app gets its own database
credential.
From your laptop,
ghayma connect --local tunnels the
site’s databases and writes its own credentials into .env.local. For a
tool or person outside Ghayma, add a named
principal: its own credential, its own level, its
own source allowlist, rotated or revoked on its own.
This output needs CLI v0.14.0 or later. An older CLI asks the platform for the database’s own login, which is refused now: it prints the platform’s sentence, which names the same ways in (on a Valkey, its old note).
A Valkey prints the same layout without a Database: row and without the
From outside Ghayma line, since a Valkey has no external principals yet:
🔌 Connection details for 'cache' (valkey)
Host: vk-cache-a1b2c3d4.pdb-<project-uuid>.svc.cluster.local
Port: 6379
Connected sites and the variables they receive:
main connect REDIS_URL, VALKEY_URL, REDIS_URL_CACHE, VALKEY_URL_CACHE
No password is shown: each site has its own credential, delivered in these variables.
From your laptop: ghayma connect --localRotating: a database’s own login is never handed out, and only an operator
rotates it. To give one app a new credential, run ghayma connections rotate database <name> --site <slug>.
ghayma db sites
View or choose which of your project’s apps may use a database. What this
command lists and edits is a connection: it opens the
database’s network policy to that app — its running pods and its
builds — and hands it the connection variables.
--add connects at the default level, connect — pick read-only instead with
ghayma connect. Every database enforces its own policy, so only a
connected app can open a connection.
A database is connected only to the sites you choose — at
create, when ghayma deploy offers it, or with
--add below — and until then it is deny-all. A site marked ⏳ is waiting
for a new PostgreSQL or Valkey database to accept connections, and connects
once it does. --add and --remove of other sites keep it waiting; --remove
naming it cancels it. A Valkey takes no new site until it runs:
❌ cache is stopped. Start it, then run this again: ghayma db start cache
❌ cache is not running yet, so no app can connect to it. Wait until ghayma db info cache shows running, then run this again.ghayma connect database <name> --site <slug>
and ghayma connections are the newer
form of the same thing, and the only one that also covers buckets and auth apps.
# Show the current access table
ghayma db sites my-postgres
# Also let the 'admin' site reach it (keeps existing grants)
ghayma db sites my-postgres --add admin
# Grant several sites at once
ghayma db sites my-postgres --add admin,api
# Revoke a site
ghayma db sites my-postgres --remove admin
# Replace the whole set with exactly these sites
ghayma db sites my-postgres --set main,adminOutput:
🗄️ Site access for 'my-postgres':
SITE NAME ACCESS
main main ⏳
admin admin -
✓ = allowed ⏳ = connecting once the database accepts connections - = blockedThe three flags are mutually exclusive. Adding a site that already has access
(or removing one that doesn’t) is reported as a no-op, not an error. Revoking
all sites (--remove every granted slug) is allowed and makes the database
unreachable from apps entirely — platform backups keep working.
Changes take effect within ~2 minutes (the network policy reconverges in the background) — no redeploy needed.
Connecting an app is only half the story: it must also use the database’s
internal hostname (…databases.svc.cluster.local, or
vk-<name>-<id8>.pdb-<project-uuid>.svc.cluster.local for a Valkey), not a
public *.db.ghayma.tech one — external hostnames are unreachable from deployed
apps whatever the connections say. See the
Internal Networking guide.
ghayma db stop / db start
Stop or start a database to save resources. Data is preserved while stopped.
ghayma db stop my-mongo
ghayma db start my-mongoghayma db delete
Permanently delete a database and all its data. Requires typing the database name to confirm:
⚠️ This will permanently delete 'my-postgres' and all its data.
Type the database name to confirm:ghayma db delete my-postgresThis permanently deletes the database and all data. Back up first if you need to preserve anything.