Deploying a production-grade Next.js application on AWS often involves a complex interplay between S3, Lambda@Edge (or App Runner), and CloudFront. While the application logic may be flawless, infrastructure deployments frequently halt due to a specific, blocking error: InvalidViewerCertificate.
This error indicates that CloudFront cannot validate the SSL/TLS certificate associated with the custom domain you are attempting to attach. It is not a code error within your Next.js application; it is an architectural strictness within the AWS Edge network.
This guide provides the root cause analysis of this failure and the infrastructure-as-code patterns required to resolve it permanently.
The Root Cause: Global Edge vs. Regional Resources
To fix the InvalidViewerCertificate error, you must understand the physical architecture of AWS CloudFront.
CloudFront is a Global service. It does not exist within a specific region like us-west-2 or eu-central-1. It consists of Points of Presence (PoPs) distributed worldwide.
However, the control plane that manages the cryptographic material (SSL/TLS certificates) for these global edge locations resides physically in US East (N. Virginia), also known as us-east-1.
Why Your Deployment Fails
When you request a certificate via AWS Certificate Manager (ACM) in the same region as your application resources (e.g., us-west-2), CloudFront cannot access it.
- Scope Isolation: Regional ACM certificates are designed for regional load balancers (ALBs) and API Gateways.
- Propagation: CloudFront requires the certificate to be distributed to every edge location globally. The internal AWS mechanism for this distribution only polls from ACM in
us-east-1. - The Error: When CloudFormation or Terraform attempts to associate a regional certificate ARN with a global CloudFront distribution, the API rejects the request with
InvalidViewerCertificate.
Solution 1: The Multi-Region Infrastructure Pattern
If you are using Infrastructure as Code (IaC) tools like Terraform, CDK, or Pulumi, you cannot simply define your ACM certificate in your default provider if that provider is not us-east-1.
You must implement a multi-region provider strategy. Below is the implementation for Terraform, which is the industry standard for defining this architecture.
The Terraform Fix
You need to explicitly define a secondary AWS provider aliased to us-east-1.
# 1. Define your default provider (where your Next.js app lives)
provider "aws" {
region = "us-west-2"
}
# 2. Define the specific provider for CloudFront Certs
provider "aws" {
alias = "us_east_1"
region = "us-east-1"
}
# 3. Request the certificate using the aliased provider
resource "aws_acm_certificate" "nextjs_cert" {
# CRITICAL: This forces the cert to be created in N. Virginia
provider = aws.us_east_1
domain_name = "app.yourdomain.com"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
# 4. Ensure validation records are created
# Note: Route53 is global, so we use the default provider here
resource "aws_route53_record" "cert_validation" {
for_each = {
for dvo in aws_acm_certificate.nextjs_cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = data.aws_route53_zone.main.zone_id
}
# 5. Wait for validation to complete
resource "aws_acm_certificate_validation" "nextjs_cert" {
provider = aws.us_east_1
certificate_arn = aws_acm_certificate.nextjs_cert.arn
validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}
# 6. Attach to CloudFront
resource "aws_cloudfront_distribution" "s3_distribution" {
# ... other config ...
viewer_certificate {
# Reference the validated certificate ARN
acm_certificate_arn = aws_acm_certificate_validation.nextjs_cert.certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
}
Solution 2: Handling CNAME Conflicts
Sometimes the InvalidViewerCertificate error masks a different issue: CNAME Overlap.
If you attempt to add app.yourdomain.com to a new CloudFront distribution, but that domain is already attached to an existing distribution (even one in a different AWS account), CloudFront will block the request. This often happens when migrating from Vercel (which uses AWS under the hood) to a custom AWS account, or when rebuilding an environment.
Diagnosing CNAME conflicts
You cannot see cross-account distributions in the AWS Console. You must use the AWS CLI to find the conflict.
Run the following command in your terminal:
aws cloudfront list-conflicting-aliases \
--distribution-id <YOUR_NEW_DISTRIBUTION_ID> \
--alias app.yourdomain.com
resolving the Conflict
If the command reveals a conflict, you have two options:
- The Manual Detach: Log into the account owning the conflicting distribution and remove the CNAME from the settings.
- Wildcard Verification (The "Takeover"): If you do not have access to the other account (e.g., a lost dev account or a 3rd party provider), you must prove ownership of the domain via DNS to force the transfer.
To force a transfer, add a TXT record to your DNS configuration (Route53):
- Name:
_cname-overlap-challenge.app.yourdomain.com - Value: (Provided by the AWS Console error message or support)
Once this TXT record propagates, re-run your deployment. AWS will verify you own the domain via DNS and forcibly disassociate the CNAME from the old distribution.
Deep Dive: Key Length and Algorithm Mismatches
A less common but valid cause for InvalidViewerCertificate is an unsupported key algorithm.
Modern ACM certificates support both RSA and ECDSA (Elliptic Curve Digital Signature Algorithm). While CloudFront supports ECDSA, older clients or specific security policies set on the minimum_protocol_version might trigger handshake failures if the certificate key type does not match the distribution's expectations.
Best Practice Configuration
For maximum compatibility and performance with Next.js applications, use the following configuration:
- Algorithm: RSA 2048 (Standard) or ECDSA P-256 (Modern/Faster).
- Protocol: TLSv1.2_2021. Avoid older security policies unless supporting legacy IoT devices.
- SNI: Always use
sni-only. Do not usevip(Dedicated IP) unless you are willing to pay $600/month per distribution.
Summary
The InvalidViewerCertificate error is rarely a bug in AWS; it is an enforcement of architectural constraints.
- Region: Ensure your ACM certificate is created in us-east-1, regardless of where your Next.js Lambdas or buckets reside.
- Validation: The certificate must be in
ISSUEDstatus before CloudFront allows the association. - Uniqueness: Ensure the CNAME is not currently claimed by a "zombie" distribution from a previous deployment.
By implementing the multi-region Terraform provider pattern outlined above, you ensure that your infrastructure definition aligns with the physical reality of the AWS global network.