Create it
- Console
- CLI and API
- Coding agent
- Open the environment, then New service › Blueprint.
- Find Amazon RDS for PostgreSQL in the catalog and pick the major version.
- Fill in the variables. Required ones are marked; the others use their defaults.
- Create the service, and deploy it now or later.
Variables and outputs
Generated fromqbm.yml at AWS/postgres/18/1.8.0, the manifest the Console form is built from.
All 41 variables
All 41 variables
All 28 outputs
All 28 outputs
Reference
From the Blueprint’s README. Creates an AWS RDS PostgreSQL 18 instance with configurable instance class, storage, backups, maintenance window, monitoring, and network settings. Storage is encrypted by default. When the blueprint creates the instance, the RDS identifier is derived fromdb_name: lowercased, each run of underscores turned into one hyphen, and a trailing hyphen dropped (AWS requirement). An adopted instance keeps its existing identifier (import_identifier), which can differ from db_name. The actual PostgreSQL database name is kept as provided.
Variables
Required
Available instance classes: every RDS instance class Qovery offers for native managed PostgreSQL and MySQL — the
db.t3, db.t4g, db.m5–db.m8g, db.r5–db.r8g (including db.r5b), db.x2g, db.x2idn and db.x2iedn families, with their Graviton (g), Intel (i), local-storage (d) and network-optimized (n) variants. db.c6gd is left out because RDS offers it only for Multi-AZ DB clusters. The full list is in qbm.yml.
Credentials
Both are optional — omit them and Qovery supplies the values, the way native managed databases did. In the console, leaving the field blank omits it. Through the API or Terraform, omit the variable rather than sending an empty string: the platform rejects an empty variable value.
Changing
db_password rotates the live instance’s master password: the value is sent as a
write-only argument, triggered by a version derived from the password itself, so a change
reaches RDS and an unchanged password sends nothing.
An adopted instance does not take part until manage_db_password is set to true. That keeps
its import plan clean, and it has a consequence worth stating plainly: while the flag is
false, editing db_password changes what the blueprint publishes without changing anything on
the instance. Consumers pick up a credential RDS will reject. On an adopted instance, either
set the flag before touching the password, or do not touch the password at all.
Setting the flag is itself a write. Until then the version that triggers the send is null in
state, so switching it to true moves that value and applies db_password to the instance —
harmless when the two already agree, and an overwrite of the live password when they do not.
Confirm the stored password is the one the instance actually has before opting in.
A rotation also obeys apply_changes_now. Left false, RDS defers the password change to the
maintenance window while the new value is published immediately — consumers redeployed in
between cannot connect. Set apply_changes_now when you rotate.
Adoption (import_identifier set) requires both explicitly. username is ForceNew on
aws_db_instance, so a defaulted value would plan a replacement and destroy the live
database; and RDS never returns the master password, so a generated one would be published
as the credential without ever being applied.
Instance & storage
Storage autoscaling. With
max_allocated_storage set, RDS grows the disk on its own when free
space stays at or below 10% for 5 minutes, up to that ceiling. It waits until the previous
storage change has finished optimizing, and grows a disk at most four times in 24 hours. Left
empty, the blueprint keeps whatever the instance has, including a ceiling set in the AWS console.
- The ceiling must be at least 10% above the current disk, not only above
allocated_storage, and on each read replica above that replica’s own disk. Once autoscaling has grown a disk, the deploy fails before changing anything if the ceiling is too close to it, and names the minimum. An unchanged ceiling is not checked, except whenallocated_storageraises the disk or a new replica is about to be created with it. A replacement that keeps the identifier is not caught: if its disk sits within 10% of the ceiling, AWS refuses it at apply, so raise the ceiling first. - It applies immediately, without a reboot, whatever
apply_changes_nowsays: RDS ignores the apply-immediately flag for a ceiling change. - A disk never shrinks. The blueprint asks for the larger of
allocated_storageand the live disk size, so a grown disk does not show as a change, and setting0after a growth turns autoscaling off at the current size. - With io1/io2 storage, AWS also requires the IOPS-to-ceiling ratio to stay within a range, and rejects a ceiling outside it when the deploy applies.
Network
By default the instance is attached to the Qovery cluster network: the DB subnet group created at cluster bootstrap (named after the cluster VPC id) and the cluster workers security group, so pods in the cluster can reach the database out of the box. On clusters deployed into an existing VPC (user-provided network), the
ClusterId tag lookup may not resolve; set db_subnet_group_name and security_group_ids explicitly in that case.
Read replicas
Read replicas are asynchronous read-only copies of the primary — point analytics/BI tools (Metabase, Superset, dashboards, ad-hoc reporting) at their endpoints to keep heavy read traffic off the primary. They inherit the primary’s engine version, storage size, storage type, and encryption, and share its database name, master username, and password; connect with the same credentials at the replica endpoint.
max_allocated_storage and cloudwatch_logs_export_enabled apply to every replica too: left unset, an existing replica keeps its own autoscaling ceiling and log exports, and a new one starts from the primary’s. Because replication is asynchronous, replicas are eventually consistent (fine for analytics, not for read-after-write). Creating replicas requires automated backups on the primary (backup_retention_period > 0, the default). Replica endpoints are exposed via the read_replica_endpoints output. Analytics tools running inside the cluster can reach them over the cluster network out of the box; set read_replica_publicly_accessible = true only for tools that live outside the VPC. To let such a tool in without opening the primary, set read_replica_publicly_accessible = true and list its egress IPs in read_replica_allowed_cidrs (e.g. the Metabase Cloud IPs for your region): the blueprint creates a dedicated security group allowing those CIDRs plus the VPC’s own CIDRs on the database port, and attaches it to the replicas instead of the primary’s groups. Replacing rather than adding is deliberate: on a Qovery-managed network the cluster workers group also carries the cluster-wide database.postgresql.allowed_cidrs rule (0.0.0.0/0 by default), which would otherwise leave a public replica reachable from anywhere. Clients inside the VPC keep access through the VPC CIDR rule. With the variable unset, replicas carry the primary’s security groups, including on an adopted instance.
Maintenance & upgrades
Backups
Deleting the service keeps a final snapshot and the automated backups by default, and both keep
costing storage until deleted by hand: the snapshot indefinitely, the backups for
backup_retention_period days. For a throwaway or test instance, set both skip_final_snapshot and
delete_automated_backups to true. The final snapshot is named
<cluster name>-<db name>-<YYYYMMDDhhmmss>: db_name slugged as for the identifier, the UTC
time the name was stamped. The cluster name is cleaned in this order: any character AWS rejects is
removed, hyphen runs are collapsed, it is cut to 160 characters to stay within the 255-character
limit, then leading and trailing hyphens are dropped. The whole name is prefixed snap- if it does
not start with a letter. It is stamped once at creation, so successive create/destroy cycles of the
same name do not collide.
Monitoring
CloudWatch log export.
cloudwatch_logs_export_enabled = true adds the postgresql log to
what the instance already exports; RDS publishes it to the log group
/aws/rds/instance/<identifier>/postgresql. false does not remove anything: the instance keeps
the exports it has, so an export set in the AWS console (upgrade, for instance) survives every
deploy.
- To stop the export, disable it in the AWS console and keep the input
false. Withtrue, the next deploy turns it back on. - The log group is not managed by the blueprint. RDS creates it; the blueprint neither sets its retention (CloudWatch defaults to never expire) nor deletes it with the instance.
- What gets logged follows the parameter group. The RDS default logs errors, failed logins and
deadlocks; set
log_min_duration_statementorauto_explainthroughdb_parametersfor more.
Misc
Parameters
Each value is either the parameter value, or an object carrying
apply_method too. RDS applies a
dynamic parameter with immediate (the default here) and refuses it for a static one, which needs
pending-reboot:
- Write values the way RDS stores them — plain integers in the parameter’s own unit (
max_wal_sizein MB,checkpoint_timeoutin seconds). Anything else is normalised by AWS and shows up as a change on every deploy. JSONtrue/falseare sent as1/0. - Overriding
shared_preload_librariesreplaces the RDS default,pg_stat_statements. Keep it in the list, or Performance Insights’ SQL statistics stop. - The blueprint never reboots the instance to apply parameters. A new instance starts on the group. On an existing
one, attaching the group for the first time, and every change to a
pending-rebootparameter, waits for a reboot: the instance showspending-rebootin the AWS console until you reboot it there. Changes to dynamic parameters apply without one. - The group is named
<identifier>-params-<suffix>and its family follows the engine major (postgres18). Withdb_parametersset, a major upgrade creates a group of the new family with the same parameters and moves the instance onto it along with the engine. RDS upgrades the read replicas as part of the primary’s upgrade, so they move onto the new group in the same deploy, and only then is the old group deleted: it is never sent a parameter its version may not know. - A major upgrade with
db_parametersset, or being cleared, needsapply_changes_now = true, and the deploy fails before changing anything otherwise. Deferred to the maintenance window, the upgrade would keep the old group attached, and it could not be deleted. Either apply the upgrade now, or upgrade first and setdb_parametersafterwards. - Clearing
db_parametersmoves the instance and replicas back todefault.postgres18and deletes the group; dynamic parameters revert straight away, static ones at the next reboot. Left unset, the blueprint does not touch the parameter group, so a group attached by other means stays in place. The blueprint recognises its own group by name,<identifier>-params-followed by 26 hex characters: do not give a group of your own a name of that shape.
Outputs
Upgrading from an earlier blueprint version
Read this before repointing a deployment at this version.-
Repointing a service from an older PostgreSQL major upgrades its engine in place. Qovery
sets
engine_versionto the highest 18.x that RDS lists as a valid upgrade target from the running version, and Terraform runs the major upgrade (downtime; withapply_changes_now = false, in the next maintenance window). An instance already upgraded through RDS to 18 is only relabelled. An instance on a custom parameter group needs a group of the new family first: RDS refuses the upgrade otherwise. From a newer major, do not repoint here: RDS cannot downgrade. -
Deleting now keeps a final snapshot and the automated backups for services created on this
version. An existing service does not change behaviour: Qovery stores every variable default when
the service is created, so repointing it here keeps
skip_final_snapshot = trueanddelete_automated_backups = true. To keep a snapshot and backups on delete, set both tofalseon the service. The upgrade itself addstime_static.createdand, with those set tofalse, updatesskip_final_snapshot,delete_automated_backupsandfinal_snapshot_identifierin place — Terraform-only arguments, nothing is sent to AWS and the instance is not rebooted. -
For an instance this blueprint created, and for an adopted instance already opted in with
manage_db_password, the first apply writes the master password once. Old state carries no record of what was last sent, so the value Qovery holds is applied. An instance whose password was rotated outside Terraform — which earlier versions of this document told you to do — is reset to the Qovery-held value, and applications using the out-of-band password stop connecting. Make the two agree before you upgrade. An adopted instance left atmanage_db_password = falseis not touched: nothing is sent, and an out-of-band rotation survives. -
manage_db_passwordis one-way. Setting it back to false after an adopted instance has been handed over leaves Terraform with a change AWS rejects as “no modifications were requested”. -
Terraform moves from 1.9.7 to 1.13.3, and
1.9.7is no longer an accepted override. State written by 1.13.3 cannot be read by 1.9.7, so a deployment cannot be repointed at an earlier blueprint version once it has applied. -
parameter_group_nameis no longer ignored. Left unset (db_parametersempty), nothing changes: Terraform sends no value and a group attached in the AWS console stays. Settingdb_parametersreplaces that group with the blueprint’s, so copy any parameters you still need into it first. -
On an adopted instance with read replicas, the replicas are now given the primary’s security
groups explicitly, even with
read_replica_allowed_cidrsunset. If they currently carry other groups (typically the VPC default group), the first apply swaps them in place: no replacement, no reboot. An instance this blueprint created is unaffected; its replicas already had these groups. -
max_allocated_storageandenabled_cloudwatch_logs_exportsare no longer ignored, and nothing changes until you set the new inputs: repointing leavesmax_allocated_storageempty andcloudwatch_logs_export_enabledfalse, and both keep what the primary and each replica have, including autoscaling and exports set in the AWS console.allocated_storagenow follows the live disk when that is larger, so a disk grown by autoscaling no longer shows as a change. Qovery can turn the log export on but not off; disable it in the AWS console.
Lifecycle ignore_changes
On the primary instance,engine_version is no longer ignored. Terraform requests the exact
version held in the internal engine_version variable, which Qovery sets on every deploy:
- the live version, while the service stays on this major
- the highest valid upgrade target, when the service moves here from an older major.
auto_minor_version_upgrade enabled, AWS may still move the running minor forward; the next
deploy then requests that newer version, so Terraform never tries to go back. Read replicas inherit
the primary’s version.
A bare major such as "18" is never sent to a live instance, because AWS resolves it to the
region’s default minor, which upgrades an older minor and is refused on a newer one. Without the
variable, an existing instance keeps its live version (read through the aws_db_instance data
source) and only a new instance gets the bare major.
enabled_cloudwatch_logs_exports and max_allocated_storage are managed, on the primary and on
the read replicas, but an unset input keeps the live value instead of clearing it: the blueprint
reads each instance through the aws_db_instance data source on every plan, so an empty
max_allocated_storage keeps the live ceiling and cloudwatch_logs_export_enabled = false keeps
the live exports. A replacement that changes the identifier (a db_name change on an instance this
blueprint created) finds no live instance and starts from the inputs alone. One that keeps it (an
adopted instance, whose identifier is import_identifier, or a storage_encrypted toggle) reads
the old instance, so the new one inherits its disk size, autoscaling ceiling and log exports.
Two attributes remain ignored on the primary:
password— the master password moved to the write-onlypassword_wo; ignoring the plain attribute stops the value left in older state reading as a removal.tags— ignored on the primary and every read replica, so tag changes from the blueprint never reach an existing database. The reason is adoption: the native path tags managed RDS withcluster_id, which the YACE CloudWatch exporter filters DB metrics on.
Required AWS IAM permissions
The credentials used to deploy this blueprint must allow the actions below. The RDS actions target instances in any region you deploy to; EC2 read actions are needed so Terraform can look up the default VPC, subnets, and security groups when none are explicitly configured. The EC2 write actions are used whileread_replica_allowed_cidrs is set, and on the apply that clears it (Terraform revokes the rules and deletes the group), so keep them until that apply has run.
monitoring_interval > 0, the supplied monitoring_role_arn must be assumable by RDS (monitoring.rds.amazonaws.com trust relationship) and grant the AmazonRDSEnhancedMonitoringRole managed policy.