RDS for PostgreSQL DB instances should publish logs to CloudWatch Logs
PostgreSQL logs contain connection attempts, query errors, deadlocks, and authentication failures. Without forwarding these to CloudWatch Logs, you lose centralized visibility into database activity. Incident responders cannot correlate application errors with database events, and retention depends entirely on the RDS instance lifecycle rather than a durable log store.
Exporting to CloudWatch also unlocks metric filters, alarms, and CloudWatch Logs Insights for ad-hoc investigation. If the instance is terminated or storage fills up, local logs may be lost permanently.
Retrofit consideration
apply_immediately setting, this may cause a brief connectivity interruption during the change window.Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
This control is enforced automatically with Compliance.tf modules. Start free trial
If you use terraform-aws-modules/rds/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}Use AWS provider resources directly. See docs for the resources involved: aws_db_instance.
resource "aws_db_instance" "this" {
allocated_storage = 20
enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
engine = "postgres"
identifier = "pofix-abc123"
instance_class = "db.t3.micro"
monitoring_interval = 60
monitoring_role_arn = "arn:aws:iam::123456789012:role/example-role"
password = "ChangeMe123!"
skip_final_snapshot = true
username = "dbadmin"
}What this control checks
For aws_db_instance resources with engine = "postgres", enabled_cloudwatch_logs_exports must include the required log types. At minimum, "postgresql" must be present; "upgrade" may also be required depending on the control's logTypes parameter. A passing configuration looks like enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]. It fails if the argument is omitted, set to an empty list, or missing one of the expected values. No additional IAM configuration is required: RDS automatically creates the necessary CloudWatch Logs log groups and streams when exports are enabled.
Common pitfalls
Omitting upgrade log type
If the control's logTypes parameter expects both "postgresql" and "upgrade", including only "postgresql" still triggers a failure. Check the parameterization before assuming the default list is sufficient.
Engine mismatch with Aurora PostgreSQL
This control targets aws_db_instance resources with engine = "postgres", not Aurora PostgreSQL clusters. Aurora PostgreSQL logging is configured on aws_rds_cluster with enabled_cloudwatch_logs_exports, which is a separate control surface evaluated independently.
Insufficient log_min_messages parameter
Enabling log export does not control what PostgreSQL actually logs. If log_statement, log_min_duration_statement, or log_connections are unset in the associated aws_db_parameter_group, the logs flowing into CloudWatch may contain very little useful signal.
CloudWatch Logs retention defaults to never expire
Declare the log group explicitly in Terraform using aws_cloudwatch_log_group and set retention_in_days before enabling exports. RDS reuses an existing log group rather than creating a new one, so without an explicit resource the group defaults to indefinite retention and storage costs grow unbounded.
Audit evidence
AWS Config evaluation results showing all RDS PostgreSQL instances as compliant for log export configuration are the primary evidence. Supporting that, the CloudWatch Logs console should show active log groups under /aws/rds/instance/<instance-id>/postgresql with recent log streams confirming logs are flowing. The RDS console's "Configuration" tab for each instance lists the published log types under "Log exports."
For deeper assurance, CloudTrail ModifyDBInstance events confirm when log exports were enabled. CloudWatch Logs retention policies on the relevant log groups demonstrate the organization is retaining logs for the required duration.
Framework-specific interpretation
SOC 2: CC7.1 and CC7.2 ask whether you can detect and respond to anomalies in system activity. For a PostgreSQL instance, that means getting database events somewhere you can actually query them. CloudWatch Logs integration is what SOC 2 auditors ask to see when reviewing database monitoring coverage.
PCI DSS v4.0: Requirement 10.2 mandates automated audit trails for system components in scope. For a PostgreSQL database that touches cardholder data, log export to CloudWatch is how you get a reviewable audit trail that meets Requirement 10's logging and monitoring obligations.
HIPAA Omnibus Rule 2013: 45 CFR 164.312(b) requires recording and examining activity in systems containing ePHI. PostgreSQL logs capture authentication events, query errors, and connection metadata. Exported to CloudWatch, they are durable and searchable without relying on local instance storage that disappears when the instance does.
ISO/IEC 27001:2022: A.8.15 (Logging) and A.8.16 (Monitoring activities) call for centralized event logging and timely detection of unauthorized activity across information processing facilities. CloudWatch log export covers both controls for RDS PostgreSQL.
GDPR: Article 32 calls for technical measures that ensure ongoing security of processing. For databases holding personal data, Article 5(2) accountability requires being able to demonstrate control over access and activity. CloudWatch Logs export makes database events searchable, retainable, and auditable.
NIS2 Directive (EU 2022/2555): Without centralized log export, incident investigation under NIS2 Article 21 means relying on whatever local logs survived on the instance. Exporting to CloudWatch puts database events in a durable store that security teams can access and search during an active incident, satisfying the directive's logging and event detection expectations.
NIST SP 800-53 Rev 5: CloudWatch log export satisfies AU-2 (Event Logging), AU-3 (Content of Audit Records), and AU-6 (Audit Record Review, Analysis, and Reporting). NIST 800-53 Rev 5's continuous monitoring expectations require exactly this kind of integration between application-level logs and a reviewable, centralized log store.
FedRAMP Moderate Baseline Rev 4: AU-2 and AU-3 require event logging with sufficient detail; AU-6 adds the expectation of automated review. CloudWatch Logs export covers both: a centralized, durable audit record of database activity and the infrastructure to run metric filters and alarms against it.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
- Compliance.tf Control:
rds_db_instance_postgres_logging_enabled - AWS Config Managed Rule:
RDS_POSTGRESQL_LOGS_TO_CLOUDWATCH - Checkov Check:
CKV_AWS_129 - Powerpipe Control:
aws_compliance.control.rds_db_instance_postgres_logging_enabled - Prowler Check:
rds_instance_integration_cloudwatch_logs - AWS Security Hub Controls:
RDS.36,RDS.9
Last reviewed: 2026-03-09