- Newest
- Most votes
- Most comments
Resolved — root cause was an expired CA certificate on the DB instance, not proxy capacity
Closing the loop on this, because the failure mode had nothing to do with what the error message says.
Root cause
Both failing DB instances were still presenting rds-ca-2019, which expired on 2024-08-22. The instance in the working VPC had already been rotated to rds-ca-rsa2048-g1. That was the only difference between the three environments — everything else really was identical, which is why the comparison never surfaced it.
RDS Proxy connects to the backend over TLS and validates the server certificate. With an expired CA the handshake never completes, so the proxy never establishes a backend connection and target registration never finishes. Role staying UNKNOWN is consistent with that: target discovery never runs.
It stayed hidden for two years because our application connects with libpq's default sslmode=prefer — TLS without certificate verification. An expired CA is invisible to a non-verifying client. The proxy was the first verifying client we ever pointed at these instances.
Fix
aws rds modify-db-instance \
--db-instance-identifier <instance> \
--ca-certificate-identifier rds-ca-rsa2048-g1 \
--apply-immediately
No restart was required (the console's "Restart required: No" was accurate). The instance returned to available in about 75 seconds, and the proxy target went to AVAILABLE / READ_WRITE roughly 30 seconds after that — after 30+ minutes of PENDING_PROXY_CAPACITY on every previous attempt. Production served HTTP 200 on its health and API endpoints throughout the rotation.
Both previously failing environments are now healthy:
insurance-flint-proxy-staging READ_WRITE AVAILABLE
insurance-flint-proxy-production READ_WRITE AVAILABLE
Worth noting for anyone who lands here: rds-ca-2019 is no longer offered by describe-certificates, so this rotation is one-way.
The one-line check I wish I had run first
aws rds describe-db-instances --db-instance-identifier <instance> \
--query 'DBInstances[0].[CACertificateIdentifier,CertificateDetails.ValidTill]'
That would have found it in seconds. Instead the PENDING_PROXY_CAPACITY wording sent us through subnet free IPs, ENIs, security groups, network ACLs, VPC DNS attributes, route tables and NAT, instance class and engine version, proxy configuration field by field, RDS-EVENT-0243, AZ IDs, service quotas, CLI-vs-Terraform creation, and a control proxy in the working VPC. All identical or ruled out.
What actually pointed at it was the RDS console's "Databases requiring certificate update" banner, which had been flagging both instances the entire time and which we had not connected to the proxy failure.
Feedback / remaining questions
-
The reported reason is misleading. A backend TLS handshake failure is surfaced as
PENDING_PROXY_CAPACITY— "DBProxy Target is waiting for proxy to scale to desired capacity" — and then as a generic "unavailable due to an internal error". Neither mentions TLS or the certificate. Is there a more specificTargetHealth.Reasonthat should have been returned here, and if not, can one be added? An expired backend CA is a deterministic, detectable condition on your side. -
Nothing was emitted to point at it.
describe-events --source-type db-proxyreturned only creation and deletion events for every proxy, in the failing VPCs and the working one alike. Enabling proxyDebugLoggingalso produced nothing about the handshake. Is there any log or event surface where the backend TLS failure is visible? If there isn't, that seems like the highest-value gap here. -
Is the mechanism as I've described it? My conclusion is inferred from the correlation — rotating the CA fixed it immediately after five failed attempts across two days — plus the fact that the working VPC was the one already on a valid CA. Please confirm whether RDS Proxy does hard-fail backend TLS validation against the instance CA, so I can document it correctly for our team.
-
Detection going forward. Other than the console banner and polling
CertificateDetails.ValidTill, is there a supported way to be alerted on an approaching or expired instance CA — an RDS event category, an EventBridge event, or a CloudWatch metric?
We have since declared ca_cert_identifier explicitly in our Terraform module; it had never been declared, which is how the setting drifted unobserved for two years.
Hi,
Given you have already ruled out couple of things while validating at your end, i would suggest to check the following as these can also cause 'UNAVAILABLE / PENDING_PROXY_CAPACITY' state for RDS Proxy.
This issue comes when there is an issue for the RDS Proxy in order to connect with target engine/instance. Thus, please check:-
-
Secrets Manager secret format issue - If the secret does not strictly follow the format {"username":"...","password":"..."}, the proxy cannot extract credentials.
-
Your RDS Proxy's IAM role must be correct/having all required permission as mentioned here - https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy-iam-setup.html#rds-proxy-iam-setup-steps
-
if the RDS Proxy monitoring user 'rdsproxyadmin' doesn't have permissions to connect to the 'postgres' database, it would lead to similar issue. You would have to grant the user 'rdsproxyadmin' the CONNECT privilege on the 'postgres' database so that the proxy can create monitoring connections on the target database and hence treat it as healthy.
GRANT CONNECT ON DATABASE postgres TO rdsproxyadmin;
This occurs because some users run below command as security best practice and that would take CONNECT privilege for RDS Proxy admin user too:-
REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;
Be aware that you will also need the users mentioned on the secrets associated to proxy to be granted as above (for health check with postgres database).
Relevant content
asked 2 years ago
asked 2 months ago
asked 2 months ago
asked 2 years ago
- AWS OFFICIALUpdated 10 months ago
- AWS OFFICIALUpdated 4 years ago
