Databases / Storage
Database storage
A database's data disk starts at its plan's size. Choose a bigger one when you create it, and grow it later without a restart. It never shrinks.
How storage works
A database keeps its data on one disk of its own, the data disk. Its plan sets the vCPUs and memory, and the plan's disk size (disk_gb in GET /plans) is the data disk's base size. You can start with more than that, and grow it at any time after:
- At create: send
storage_gbto start bigger than the plan's disk. - Later: grow it with
resize-storage. The filesystem grows online; the database keeps running and serving connections. - Never smaller. A data disk only grows. There is no way to shrink one, so grow in steps as you need the space rather than far ahead of it.
vCPUs and memory stay the plan's either way: storage is chosen separately from the plan.
Allowed sizes
Each zone's limits, and the price per GB, are in the catalogue, under each engine's storage in GET /database-engines. Read them from there in code rather than hard-coding them:
{
"engine": "postgresql",
"storage": [
{ "zone_id": "af-abj-2", "min_gb": 0, "min_is_plan_disk": true, "max_gb": 2000, "step_gb": 10,
"price_per_gb_month_minor": 15000, "currency": "NGN" }
]
}min_gb 0 (min_is_plan_disk: true) means the plan's own disk is the smallest size. Today both zones are:
af-abj-1 and af-abj-2 | |
|---|---|
| Smallest | The plan's own disk size (the base) |
| Largest | 2,000 GB |
| Step | 10 GB: above the base, a size must be a multiple of 10 |
The base size is always allowed, even when it is not itself a multiple of 10. Anything above it must land on a 10 GB step. So for a plan whose disk is 25 GB, 25, 30, 40 … 2000 are valid, and 35 is not.
A size outside these rules is refused with 422 VALIDATION_FAILED and, in errors, code INVALID_DATABASE_STORAGE on the field storage_gb.
Choose the size at create
Add storage_gb to the create request. Leave it out to get the plan's disk size.
$ curl https://api.pantechdynamics.com/public/v1/databases \ -H "Authorization: Bearer $PANTECH_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "name": "orders-db", "engine": "postgresql", "version": "18", "plan_slug": "starter", "zone_id": "af-abj-2", "subnet_id": "snet_…", "storage_gb": 100 }'The order's amount_minor, the upfront payment, is priced for the size you chose, not the plan's. See pricing.
Grow it later
In the console, press Increase storage in the database's Storage card and choose the new size. It grows online with no restart, and is billed at the old size until the new one lands. The database must be running, with no other change in progress.
With the API:
$ curl -X POST https://api.pantechdynamics.com/public/v1/databases/db_…/resize-storage \ -H "Authorization: Bearer $PANTECH_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"storage_gb": 200}'{
"operation_id": "op_…",
"resource_id": "db_…",
"status": "submitting"
}The new size must be:
- larger than the database's current
data_volume_size_gb, - at most 2,000 GB,
- a multiple of 10.
And the database must be running: the disk is grown first, then the filesystem inside it, which needs the database's machine up. A stopped database is refused with 409 DATABASE_NOT_RUNNING; start it first.
Follow the operation until it is succeeded. While it runs, the database reads:
{
"data_volume_size_gb": 100,
"pending_data_volume_size_gb": 200
}data_volume_size_gbis the size in place and billed. It changes only when the resize has finished, and the database's own filesystem reports the new size.pending_data_volume_size_gbis the size a resize in flight is growing to, ornullwhen none is.
One resize at a time: another request while one is in flight is 409 DATABASE_STORAGE_RESIZE_IN_PROGRESS. Retrying the same request with the same Idempotency-Key is always safe; it returns the operation already running.
If a resize fails
The operation ends failed with a failure.code, pending_data_volume_size_gb goes back to null, and data_volume_size_gb and the bill are unchanged. Your data is untouched.
failure.code | What happened | What to do |
|---|---|---|
DATABASE_STORAGE_RESIZE_FAILED | The disk could not be grown | Try again. If it fails again, contact support with the operation id |
DATABASE_STORAGE_GROW_FAILED | The disk grew but the filesystem inside it did not, or the database could not be reached | Check the database is running, then try again with the same size |
In the second case the disk may already be bigger than data_volume_size_gb. You are not billed for that extra space until a later resize confirms it.
With the CLI
$ pantech db create --name orders-db --engine postgresql --version 18 --plan starter \ --zone af-abj-2 --subnet web --storage-gb 100$ pantech db storage resize orders-db --storage-gb 200Grow the storage of orders-db from 100 GB to 200 GB? It is billed at the new size once grown, and can never shrink. [y/N] ydb storage resize checks the size is larger than the current one before it asks, then waits for the operation; pass --no-wait to get its id at once, and --yes to skip the question in scripts. pantech db get shows the size and any resize in flight.
With Terraform
In the provider's next release:
resource "pantechdynamics_database" "orders" {
name = "orders-db"
engine = "postgresql"
version = "18"
plan_slug = "starter"
zone_id = "af-abj-2"
subnet_id = pantechdynamics_subnet.data.id
storage_gb = 100
password_wo = var.orders_db_password
password_wo_version = 1
}Raising storage_gb and applying grows the disk in place. Lowering it is refused at plan time, never a replacement: Terraform will not delete a database to make its disk smaller. Leaving storage_gb out keeps the plan's size.
Pricing
Storage is priced per GB-month (price_per_gb_month_minor in the catalogue, for a 730-hour month), like block storage, and billed by the hour on the confirmed size (data_volume_size_gb):
- At create, the upfront payment covers the plan with the size you chose. A database at the plan's own size costs exactly what a VM in a VPC on that plan costs; every GB above it adds the per-GB storage rate.
- Growing later takes no upfront payment, the same as resizing a machine. The larger disk is billed hourly from the moment the resize completes, and invoiced with everything else. Growing is refused only when your account cannot take on new charges (suspended, or with an invoice past due).
- A stopped database still pays for its disk, at its full size.
To price a size before choosing it, estimate the plan with the extra gigabytes as extra_storage_gb:
$ curl https://api.pantechdynamics.com/public/v1/pricing/estimate \ -H "Authorization: Bearer $PANTECH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "currency": "NGN", "machines": [{"plan_slug": "starter", "quantity": 1, "running_hours": 730, "placement": "vpc"}], "extra_storage_gb": 75 }'Here 75 is the size you want minus the plan's disk_gb: 100 GB on a plan with a 25 GB disk.
Watching how full it is
A full data disk stops the engine accepting writes. Keep an eye on it from inside the engine:
SELECT pg_size_pretty(sum(pg_database_size(datname))) FROM pg_database;SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 1) AS gb
FROM information_schema.tables;Compare that with data_volume_size_gb, and grow the disk well before it is full: write-ahead logs, temporary files and indexes being rebuilt all need room beyond the data itself.