This note covers four critical ELB features that come up frequently on the SAA-C03 exam: Sticky Sessions, Cross-Zone Load Balancing, SSL/TLS Certificates with SNI, and Connection Draining / Deregistration Delay. Each one changes how the load balancer routes, secures, or gracefully handles traffic — and understanding the nuances (especially the defaults per LB type) is essential.
1. Sticky Sessions (Session Affinity)
What Is It?
Normally, a load balancer distributes requests across all healthy backend instances in a round-robin fashion. With sticky sessions enabled, a client that makes a first request to the load balancer is "stuck" to the same backend instance for all subsequent requests — as long as the stickiness cookie hasn't expired.
WITHOUT Sticky Sessions:
┌────────┐ ┌─────────┐ Request 1 ──▶ EC2-A
│ Client │────▶│ ALB │ Request 2 ──▶ EC2-B (round-robin)
└────────┘ └─────────┘ Request 3 ──▶ EC2-C
WITH Sticky Sessions:
┌────────┐ ┌─────────┐ Request 1 ──▶ EC2-A
│ Client │────▶│ ALB │ Request 2 ──▶ EC2-A (same instance!)
└────────┘ └─────────┘ Request 3 ──▶ EC2-A
│
└── Cookie: AWSALB=<hash>; Expires=<tomorrow>
How It Works — The Cookie Mechanism
The load balancer sends a cookie to the client's browser as part of the HTTP response. On every subsequent request, the browser sends that cookie back, and the load balancer reads it to determine which backend instance to route to. When the cookie expires, the client may be redirected to a different instance.
┌────────┐ ┌─────────┐ ┌─────────┐
│ Client │── GET /page ──────▶│ ALB │── Forward ────────▶│ EC2-A │
│ │ │ │ │ │
│ │◀── 200 OK ────────│ │◀── Response ───────│ │
│ │ Set-Cookie: │ │ │ │
│ │ AWSALB=abc123 │ │ │ │
│ │ Expires=1d │ │ │ │
│ │ │ │ │ │
│ │── GET /next ──────▶│ │ │ │
│ │ Cookie: │ Reads │ │ │
│ │ AWSALB=abc123 │ cookie │── Route to EC2-A ─▶│ │
└────────┘ └─────────┘ └─────────┘
Supported Load Balancers
| Load Balancer | Sticky Sessions? | Notes |
|---|---|---|
| CLB | ✅ Yes | Duration-based only |
| ALB | ✅ Yes | Duration-based + Application-based |
| NLB | ✅ Yes | Uses source IP hash (no cookie) |
Cookie Types — Deep Dive
There are two categories of stickiness cookies, and within application-based, there are two sub-types:
| Category | Sub-Type | Generated By | Cookie Name | Expiry Set By |
|---|---|---|---|---|
| Duration-based | — | Load balancer | AWSALB (ALB), AWSELB (CLB) |
Load balancer (you set duration) |
| Application-based | LB-generated | Load balancer | AWSALBAPP |
Application |
| Application-based | Custom | Your application | Custom name (you choose) | Application |
You must not use the following names for custom cookies — they are reserved by ELB:
AWSALBAWSALBAPPAWSALBTG
Configuration
| Setting | Details |
|---|---|
| Where to configure | Target Group level → Actions → Edit attributes → Stickiness |
| Stickiness duration | 1 second to 7 days |
| Types available | Load balancer generated cookie OR Application-based cookie |
| App cookie name | Required if using application-based (e.g., MYCUSTOMCOOKIEAPP) |
The Risk: Load Imbalance
Sticky sessions can cause load imbalance. If one user generates heavy traffic and is "stuck" to a single instance, that instance gets overloaded while others sit idle. This is the primary trade-off.
Imbalanced Scenario:
┌─────────┐
│ ALB │
└────┬────┘
│
├──▶ EC2-A ████████████████ (80% load — sticky heavy user)
├──▶ EC2-B ██ (10% load)
└──▶ EC2-C ██ (10% load)
When to Use Sticky Sessions
- ✅ Application stores session data locally on the instance (login state, shopping cart)
- ✅ Legacy applications that can't use external session stores
- ❌ Better alternative: store sessions in ElastiCache or DynamoDB and make the app stateless
Hands-On Walkthrough
- Open your ALB in the EC2 console
- Go to Target Groups → select your target group
- Click Actions → Edit attributes
- Scroll to Target selection configuration → Stickiness
- Turn stickiness On
- Choose type:
- Load balancer generated cookie — set duration (e.g., 1 day)
- Application-based cookie — enter your custom cookie name
- Click Save changes
- Open your ALB DNS in a browser → refresh multiple times → you'll always hit the same instance
- Open Developer Tools → Network tab → Cookies to see the
AWSALBcookie with its expiry
Without stickiness: refreshing the page cycles through different instances (different AZ/instance IDs in the response). With stickiness: every refresh returns the same instance. Check the Set-Cookie response header and the Cookie request header in your browser's dev tools.
2. Cross-Zone Load Balancing
The Problem
When you create a load balancer across multiple AZs, each AZ gets its own load balancer node. By default (for NLB/GWLB), each node only distributes traffic to instances within its own AZ. If you have an uneven number of instances per AZ, this creates a severe imbalance.
With vs Without Cross-Zone Load Balancing
SCENARIO: 10 total instances — 2 in AZ1, 8 in AZ2
Client sends 50% to each AZ's LB node
┌─────────────────────────────────────────────────────────────────────┐
│ WITH Cross-Zone Load Balancing │
│ │
│ AZ1 (LB Node) AZ2 (LB Node) │
│ Receives 50% Receives 50% │
│ │ │ │
│ └──────────┬───────────────┘ │
│ │ │
│ Distributes evenly across ALL 10 instances │
│ │
│ AZ1: EC2-A (10%) EC2-B (10%) │
│ AZ2: EC2-C (10%) EC2-D (10%) EC2-E (10%) EC2-F (10%) │
│ EC2-G (10%) EC2-H (10%) EC2-I (10%) EC2-J (10%) │
│ │
│ Result: ==Every instance gets exactly 10%== ✅ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ WITHOUT Cross-Zone Load Balancing │
│ │
│ AZ1 (LB Node) AZ2 (LB Node) │
│ Receives 50% Receives 50% │
│ │ │ │
│ ▼ ▼ │
│ Only sends to AZ1 Only sends to AZ2 │
│ instances instances │
│ │
│ AZ1: EC2-A (==25%==) EC2-B (==25%==) ← OVERLOADED! │
│ AZ2: EC2-C (6.25%) EC2-D (6.25%) EC2-E (6.25%) EC2-F (6.25%) │
│ EC2-G (6.25%) EC2-H (6.25%) EC2-I (6.25%) EC2-J (6.25%) │
│ │
│ Result: AZ1 instances get ==4x more traffic== than AZ2 ❌ │
└─────────────────────────────────────────────────────────────────────┘
Defaults & Charges — Critical for Exam
| Load Balancer | Cross-Zone Default | Inter-AZ Data Charges | Can Override? |
|---|---|---|---|
| ALB | Always ON | No charge | Yes — per target group (inherit / force on / force off) |
| NLB | OFF | Charged if enabled | Yes — at LB attributes level |
| GWLB | OFF | Charged if enabled | Yes — at LB attributes level |
| CLB | OFF | No charge if enabled | Yes — at LB attributes level |
- ALB: cross-zone is always on by default, no extra charges
- NLB/GWLB: cross-zone is off by default, you pay for inter-AZ data if you enable it
- ALB allows per-target-group override: inherit (default), force on, or force off
- CLB: off by default, but no charges if you enable it (unlike NLB/GWLB)
Why Inter-AZ Data Costs Matter
In AWS, data transfer between Availability Zones normally costs money. When cross-zone load balancing is enabled, the LB node in AZ1 sends traffic to instances in AZ2 — that's inter-AZ data transfer. ALB absorbs this cost for you. NLB and GWLB pass it on.
Hands-On Walkthrough
NLB / GWLB:
- Go to EC2 Console → Load Balancers → select your NLB or GWLB
- Scroll down to Attributes → you'll see "Cross-zone load balancing: Off"
- Click Edit → toggle On
- Note the warning: "This may include regional data transfer charges"
ALB:
- Select your ALB → Attributes → "Cross-zone load balancing: On" (always)
- This cannot be turned off at the LB level
- To override: go to Target Groups → select a target group → Attributes → Edit
- Under "Cross-zone load balancing": choose Inherit (default), On, or Off
Cross-zone load balancing
3. SSL/TLS Certificates
What Is SSL/TLS?
SSL (Secure Sockets Layer) and TLS (Transport Layer Security) are cryptographic protocols that encrypt traffic in transit between the client and the load balancer. TLS is the newer, more secure version — but everyone (including AWS) still calls it "SSL" colloquially.
┌────────┐ HTTPS (encrypted) ┌─────────┐ HTTP (unencrypted) ┌─────────┐
│ Client │ ═══════════════════▶ │ ELB │ ──────────────────────▶ │ EC2 │
│ │ Public Internet │ │ Private VPC Network │ │
└────────┘ └─────────┘ └─────────┘
│
├── Loads X.509 certificate
├── Performs SSL termination
└── Decrypts HTTPS → forwards HTTP
The load balancer decrypts the HTTPS traffic (terminates the SSL connection) and forwards unencrypted HTTP to the backend EC2 instances over the private VPC network. This offloads the CPU-intensive encryption work from your instances.
Key Concepts
| Concept | Detail |
|---|---|
| Certificate type | X.509 (SSL/TLS server certificate) |
| Management | AWS Certificate Manager (ACM) — provision, manage, deploy certs |
| Upload own cert | Yes — paste private key + certificate body + chain into ACM |
| HTTPS listener | Must specify a default certificate |
| Multiple domains | Add optional list of certs to support multiple domains via SNI |
| Security policy | Configurable — choose which SSL/TLS protocol versions to support (for legacy clients) |
| Certificate Authorities | Comodo, Symantec, GoDaddy, GlobalSign, DigiCert, Let's Encrypt, etc. |
| Expiration | SSL certs have an expiration date and must be renewed regularly |
The Lock Icon
When you visit a website and see a 🔒 lock icon in the browser address bar, that means the connection is encrypted with SSL/TLS. If you see a ⚠️ warning instead, the traffic is not encrypted — don't enter sensitive information.
SNI (Server Name Indication) — Critical for Exam
The Problem SNI Solves
Imagine you have one ALB serving two different websites: www.mycorp.com and domain1.example.com. Each website needs its own SSL certificate. Without SNI, you'd need a separate load balancer for each domain. SNI solves this by letting the client tell the server which hostname it wants during the initial SSL handshake.
How SNI Works
┌──────────────────────────────────────────────────────────────────────┐
│ SNI (Server Name Indication) │
│ │
│ Client 1 │
│ "I want www.mycorp.com" │
│ │ │
│ │ TLS ClientHello: │
│ │ server_name = "www.mycorp.com" │
│ ▼ │
│ ┌─────────┐ Uses mycorp.com cert ┌──────────────────────┐ │
│ │ │ ─────────────────────────▶ │ Target Group 1 │ │
│ │ ALB │ │ (www.mycorp.com) │ │
│ │ │ └──────────────────────┘ │
│ │ Certs: │ │
│ │ ├ mycorp.com │
│ │ └ domain1.example.com │
│ │ │ ┌──────────────────────┐ │
│ │ │ ─────────────────────────▶ │ Target Group 2 │ │
│ └─────────┘ Uses domain1 cert │ (domain1.example) │ │
│ ▲ └──────────────────────┘ │
│ │ │
│ Client 2 │
│ "I want domain1.example.com" │
└──────────────────────────────────────────────────────────────────────┘
SNI Support by Load Balancer Type
| Load Balancer | Multiple SSL Certs? | SNI Support? | What To Do Instead? |
|---|---|---|---|
| CLB | No — only 1 cert | ❌ No SNI | Need multiple CLBs (one per domain) |
| ALB | Yes — multiple listeners | ✅ SNI | Use listener rules to route by hostname |
| NLB | Yes — multiple listeners | ✅ SNI | Same as ALB |
| CloudFront | Yes | ✅ SNI | Covered in CloudFront section |
"Multiple SSL certificates on one load balancer" → ALB or NLB with SNI. If the question mentions CLB, the answer is "use multiple CLBs."
SNI certificate selection
Hands-On: Adding HTTPS Listener
On ALB:
- Go to EC2 Console → Load Balancers → select your ALB
- Click Listeners → Add listener
- Protocol: HTTPS, Port: 443
- Default action: Forward to a target group
- Under Secure listener settings:
- Security policy: Choose a policy (default is fine for most cases; older policies support legacy SSL/TLS versions)
- Default SSL/TLS certificate: Choose from:
- ACM (AWS Certificate Manager) — recommended
- IAM — not recommended (legacy method)
- Import — paste private key + certificate body + chain
- Click Add
On NLB:
- Same process, but protocol is TLS (not HTTPS)
- Additional option: ALPN (Application-Layer Protocol Negotiation) — advanced TLS setting
The easiest way is to provision a free public certificate in ACM and select it when creating the HTTPS/TLS listener. ACM handles automatic renewal.
4. Connection Draining / Deregistration Delay
What Is It?
When an instance is being deregistered from a target group (e.g., scaling down, failing health checks, manual removal), there may be in-flight requests still being processed by that instance. Connection draining gives those requests time to complete gracefully before the instance is fully removed.
┌──────────────────────────────────────────────────────────────────────┐
│ CONNECTION DRAINING IN ACTION │
│ │
│ ┌────────┐ │
│ │User A │──── Existing request ────▶ EC2-A (DRAINING) │
│ │(active)│ Still processing... │ ⏳ Completing in-flight │
│ └────────┘ Connection allowed │ requests... │
│ │ │
│ ┌────────┐ ┌─────────┐ │ │
│ │User B │────▶│ ELB │──✗──────▶│ NEW connections BLOCKED │
│ │ (new) │ │ │ │ │
│ └────────┘ │ │ └──────────────────────────────┘
│ │ │ │
│ │ │──────────▶ EC2-B (HEALTHY) ✅ │
│ │ │──────────▶ EC2-C (HEALTHY) ✅ │
│ └─────────┘ │
│ │
│ After draining period expires: │
│ EC2-A is fully deregistered, all connections closed │
└──────────────────────────────────────────────────────────────────────┘
Naming Convention
| Load Balancer | Feature Name |
|---|---|
| CLB | Connection Draining |
| ALB / NLB | Deregistration Delay |
Same concept, different names. The exam may use either term.
Configuration Parameters
| Parameter | Value |
|---|---|
| Default | 300 seconds (5 minutes) |
| Range | 1 to 3,600 seconds |
| Disable | Set to 0 (no draining — connections cut immediately) |
Choosing the Right Duration
The draining duration should match your application's request patterns:
Request Duration vs Draining Time:
Short requests (< 1 sec): Draining = 30 seconds
├── API calls, web pages
├── Instance freed quickly
└── Minimal impact on scaling speed
Medium requests (1-30 sec): Draining = 60-120 seconds
├── Form submissions, queries
└── Balanced approach
Long requests (30+ sec): Draining = 300-3600 seconds
├── File uploads, video processing
├── Instance stays longer
└── Slower scaling response
- Short-lived requests (API calls, web pages): set draining to 30 seconds — instances are freed quickly for replacement
- Long-lived requests (file uploads, WebSocket connections): set draining to 300+ seconds — but the trade-off is slower instance turnover
- Disable (0) only if your application handles reconnection gracefully
What Triggers Draining?
| Trigger | Description |
|---|---|
| Health check failure | Instance marked unhealthy → enters draining |
| Manual deregistration | You remove an instance from the target group |
| ASG scale-in | Auto Scaling terminates an instance |
| ASG instance refresh | Rolling replacement of instances |
Lifecycle During Draining
Timeline:
─────────────────────────────────────────────────────────▶ Time
│ Instance healthy │ Draining starts │ Draining period │ Terminated │
│ (serving all │ (trigger event) │ (in-flight only)│ (removed) │
│ requests) │ │ │ │
│ │ │
│ New requests │ Existing │
│ → other │ connections │
│ instances │ complete or │
│ │ timeout │
Summary Comparison
| Feature | What It Does | Key Default | Exam Keyword |
|---|---|---|---|
| Sticky Sessions | Routes client to same instance via cookie | Off | "Session affinity", "AWSALB cookie" |
| Cross-Zone LB | Distributes traffic evenly across all AZs | ALB: On (free), NLB/GWLB: Off (paid) | "Even distribution", "inter-AZ" |
| SSL/TLS + SNI | Multiple SSL certs on one LB | — | "Multiple domains", "SNI", "ACM" |
| Connection Draining | Graceful shutdown for in-flight requests | 300 seconds | "Deregistration delay", "in-flight" |
Questions & Answers
Q1: What are sticky sessions and how do they work?
Answer:
Sticky sessions (session affinity) ensure a client is always routed to the same backend instance using a cookie. The load balancer sends a cookie (e.g., AWSALB) with an expiration date. On subsequent requests, the browser sends the cookie back, and the LB reads it to route to the same instance. When the cookie expires, the client may be redirected to a different instance. Supported on CLB, ALB, and NLB.
Q2: What are the two types of stickiness cookies and how do they differ?
Answer:
- Duration-based cookies: Generated by the load balancer. Cookie name is
AWSALB(ALB) orAWSELB(CLB). Expiry duration is set by you (1 second to 7 days) at the target group level. - Application-based cookies: Can be generated by the LB (cookie name:
AWSALBAPP) or by your application (custom name). Expiry is controlled by the application. You must not use reserved names (AWSALB,AWSALBAPP,AWSALBTG).
Q3: What is the main risk of enabling sticky sessions?
Answer:
Load imbalance. If a "sticky" user generates heavy traffic, their assigned instance gets overloaded while other instances sit idle. The better architectural pattern is to store session data externally (in ElastiCache or DynamoDB) and make the application stateless.
Q4: What is cross-zone load balancing and why does it matter?
Answer:
Cross-zone load balancing distributes traffic evenly across all registered instances in all AZs, regardless of which AZ the LB node received the request. Without it, traffic stays within each AZ — if you have 2 instances in AZ1 and 8 in AZ2, AZ1 instances get 25% each while AZ2 instances get only 6.25% each. With cross-zone enabled, all 10 instances get 10% each.
Q5: What are the cross-zone load balancing defaults for each LB type?
Answer:
| LB Type | Default | Inter-AZ Charges |
|---|---|---|
| ALB | Always ON | No charge |
| NLB | OFF | Charged if enabled |
| GWLB | OFF | Charged if enabled |
| CLB | OFF | No charge if enabled |
ALB allows per-target-group override (inherit / force on / force off).
Q6: What is SNI and which load balancers support it?
Answer:
Server Name Indication (SNI) allows loading multiple SSL certificates on one load balancer for different domains. The client specifies the desired hostname during the TLS handshake (ClientHello), and the LB selects the correct certificate. Supported on ALB, NLB, and CloudFront. CLB does NOT support SNI — you need one CLB per SSL certificate.
Q7: How many SSL certificates can a CLB have vs an ALB?
Answer:
- CLB: Only one SSL certificate. For multiple domains, you need multiple CLBs.
- ALB/NLB: Multiple SSL certificates via multiple listeners using SNI.
This is why CLB is considered legacy — ALB/NLB are far more flexible.
Q8: What is connection draining and what is it called on ALB/NLB?
Answer:
Connection draining gives in-flight requests time to complete when an instance is being deregistered or marked unhealthy. New requests are routed to other healthy instances. On CLB it's called Connection Draining. On ALB/NLB it's called Deregistration Delay. Default is 300 seconds, range is 1–3,600 seconds, and setting it to 0 disables it.
Q9: How should you set the connection draining duration?
Answer:
Match it to your request patterns:
- Short requests (API calls, web pages): set to 30 seconds — instances are freed quickly
- Long requests (file uploads, WebSocket): set to 300+ seconds — but slower instance turnover
- Disable (0): only if your app handles reconnection gracefully
The trade-off: longer draining = more graceful shutdown but slower scaling response.
Q10: Where are SSL/TLS certificates managed in AWS and what are the options?
Answer:
Certificates are managed in AWS Certificate Manager (ACM). When creating an HTTPS/TLS listener, you can:
- Select a certificate from ACM (recommended — free public certs with auto-renewal)
- Select from IAM (legacy method, not recommended)
- Import your own certificate (paste private key + body + chain)
You must specify a default certificate for the HTTPS listener, then optionally add more certs for SNI.
Check yourself
Quiz
Flashcards
Click the card (or focus it), then use ← → to move and Space to flip.