HTTPS & TLS Termination
Serving your application over HTTPS (HTTP Secure — encrypted web traffic) is no longer optional. Browsers warn users away from plain HTTP, and most compliance rules require encryption in transit. The good news is that an Application Load Balancer (ALB — a Layer 7 load balancer that routes web traffic) can handle all the encryption work for you. You attach a free certificate, add an HTTPS listener on port 443, and redirect plain HTTP to HTTPS so no request is ever served unencrypted.
What “TLS termination” means
TLS (Transport Layer Security — the modern protocol behind HTTPS) encrypts data between the browser and your server. “Terminating” TLS means a specific component decrypts the traffic and from there it continues as plain text. With an ALB, the load balancer does the decryption. The browser talks to the ALB over an encrypted connection, the ALB decrypts the request, and then forwards it to your backend instances (called targets).
This is convenient because your application servers never deal with certificates or encryption — the ALB does the heavy lifting. The trade-off is what happens behind the load balancer, which we cover below.
Getting a certificate from ACM
AWS Certificate Manager (ACM — a service that issues and renews TLS certificates) gives you public certificates for free, and it auto-renews them so they never expire on you. You prove you own the domain (usually by adding a DNS record), and ACM issues the certificate.
Gotcha: A public ACM certificate must live in the same Region as the load balancer that uses it. An ALB in
us-west-2cannot use a certificate issued inus-east-1. The one exception is Amazon CloudFront (AWS’s content delivery network), which always requires its certificate inus-east-1no matter where your users are. Request the certificate in the right Region from the start.
Request a certificate — Console
- Open the AWS Certificate Manager console in the same Region as your ALB.
- Click Request a certificate, choose Request a public certificate, then Next.
- Enter your domain name, for example
app.example.com(add a wildcard*.example.comif you want to cover subdomains). - Choose DNS validation (recommended — it enables auto-renewal).
- Click Request, then open the certificate and click Create records in Route 53 (or copy the CNAME record into your DNS provider).
- Wait a few minutes until Status shows Issued.
Request a certificate — CLI
aws acm request-certificate \
--domain-name app.example.com \
--validation-method DNS \
--region us-west-2
Output:
{
"CertificateArn": "arn:aws:acm:us-west-2:111122223333:certificate/0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d"
}
You then add the DNS validation record ACM gives you. Once validated, the status becomes ISSUED.
Adding an HTTPS listener
A listener is a rule that checks for connections on a port and decides what to do with them. To serve HTTPS, you add a listener on port 443 that uses your certificate.
Console steps
- Open the EC2 console and go to Load Balancers.
- Select your ALB and open the Listeners and rules tab.
- Click Add listener.
- Set Protocol to HTTPS and Port to 443.
- Under Default actions, choose Forward to target group and pick your target group.
- Under Secure listener settings, choose a Security policy (see the table below).
- Under Default SSL/TLS certificate, select From ACM and pick the certificate you issued.
- Click Add.
CLI command
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:us-west-2:111122223333:loadbalancer/app/my-alb/0a1b2c3d4e5f \
--protocol HTTPS --port 443 \
--ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 \
--certificates CertificateArn=arn:aws:acm:us-west-2:111122223333:certificate/0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d \
--default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-west-2:111122223333:targetgroup/my-tg/0a1b2c3d4e5f
Output:
{
"Listeners": [
{
"ListenerArn": "arn:aws:elasticloadbalancing:us-west-2:111122223333:listener/app/my-alb/0a1b2c3d4e5f/abcd1234ef567890",
"Port": 443,
"Protocol": "HTTPS",
"SslPolicy": "ELBSecurityPolicy-TLS13-1-2-2021-06"
}
]
}
Choosing a security policy
A security policy controls which TLS versions and ciphers (encryption algorithms) the ALB will accept. Newer policies drop older, weaker protocols.
| Security policy | TLS versions | When to use |
|---|---|---|
ELBSecurityPolicy-TLS13-1-2-2021-06 | TLS 1.3 and 1.2 | Recommended default. Modern and secure, works for the vast majority of clients. |
ELBSecurityPolicy-TLS13-1-3-2021-06 | TLS 1.3 only | Strictest. Use when compliance requires TLS 1.3 and all clients are modern. |
ELBSecurityPolicy-FS-1-2-Res-2020-10 | TLS 1.2 with forward secrecy | When an auditor demands forward secrecy on every connection. |
ELBSecurityPolicy-2016-08 | TLS 1.0, 1.1, 1.2 | Avoid unless you must support very old clients; allows weak TLS 1.0/1.1. |
Tip: Start with
ELBSecurityPolicy-TLS13-1-2-2021-06. Only restrict further if a compliance requirement forces it, because dropping TLS 1.2 can lock out older devices.
Redirecting HTTP to HTTPS
If you keep a plain HTTP listener on port 80, you should make it redirect to HTTPS rather than serve content. This guarantees every visitor ends up on an encrypted connection.
Console
- In Listeners and rules, select the HTTP : 80 listener and click Edit listener (or add one).
- Set the Default action to Redirect to URL.
- Set protocol HTTPS, port 443, and Status code 301 (a permanent redirect).
- Save.
CLI
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:us-west-2:111122223333:loadbalancer/app/my-alb/0a1b2c3d4e5f \
--protocol HTTP --port 80 \
--default-actions '[{"Type":"redirect","RedirectConfig":{"Protocol":"HTTPS","Port":"443","StatusCode":"HTTP_301"}}]'
Output:
{
"Listeners": [
{
"ListenerArn": "arn:aws:elasticloadbalancing:us-west-2:111122223333:listener/app/my-alb/0a1b2c3d4e5f/fedc0987ba654321",
"Port": 80,
"Protocol": "HTTP"
}
]
}
Terminate at the ALB vs end-to-end encryption
The big decision is what happens between the ALB and your targets.
| Approach | How traffic to targets looks | When to use |
|---|---|---|
| Terminate at the ALB | Plain HTTP from ALB to instances | Default. Simplest, lowest cost. Fine when the ALB and targets sit in the same trusted VPC (a private network in AWS). |
| Re-encrypt (end-to-end) | HTTPS from ALB to instances too | Use when compliance (PCI, HIPAA) requires encryption all the way, or traffic crosses untrusted networks. |
When you terminate at the ALB, traffic from the load balancer to your instances travels as plain text inside your VPC. For most apps in a private subnet that is acceptable. If your rules require encryption everywhere, configure your target group with the HTTPS protocol so the ALB re-encrypts before forwarding — your instances then need their own certificates.
Cost note: Public ACM certificates are free and the ALB charges nothing extra for HTTPS itself. You pay only the standard ALB hourly rate (around $0.0225/hour in
us-east-1) plus LCU usage. End-to-end re-encryption adds a little CPU cost on your instances but no extra AWS fee.
Best practices
- Request the ACM certificate in the same Region as the ALB (and in
us-east-1for CloudFront). - Always use DNS validation so ACM auto-renews certificates and you never face a sudden expiry.
- Redirect port 80 to 443 with a 301 so no request is ever served over plain HTTP.
- Pick
ELBSecurityPolicy-TLS13-1-2-2021-06unless compliance forces a stricter policy. - Use a wildcard certificate (
*.example.com) when you host many subdomains behind one ALB. - Re-encrypt to targets only when compliance truly requires it — otherwise keep it simple with TLS termination at the ALB.
- Restrict the ALB’s security group to allow port 443 from the internet, and lock target security groups to accept traffic only from the ALB.