Exam Guide: Developer - Associate ποΈ Domain 4: Troubleshooting And Optimization π Task 3: Optimize Applications By Using AWS Services And Features This task is about making applications faster, cheaper, and more efficient. You need to understand Lambda concurrency and memory tuning, caching at every layer (CloudFront, API Gateway, ElastiCache), messaging optimization with SNS filter policies, and how to read metrics to find bottlenecks. Choose the right optimization for a given symptom such as high latency, throttling, slow stream processing, or runaway cost, and etc. π Concepts Lambda Concurrency Types Type What It Does Cost Use Case Unreserved Shared pool (default 1,000 per region) Pay per invocation Default for most functions Reserved Guarantees capacity AND caps the function No extra cost Protect downstream services, guarantee capacity Provisioned Pre-warms execution environments Pay even when idle Eliminate cold starts for latency-sensitive functions π‘ Reserved concurrency does double duty. It guarantees a function gets that many concurrent executions AND prevents it from exceeding that number. Use it to stop a busy function from starving others, or to protect a downstream database from too many connections. Provisioned concurrency is the only thing that eliminates cold starts, but you pay for it 24/7. The Concurrency Formula Concurrent executions = (invocations per second) Γ (average duration in seconds) Enter fullscreen mode Exit fullscreen mode Example: 100 requests/second Γ 0.5 seconds = 50 concurrent executions needed. Memory and CPU Relationship Lambda allocates CPU proportionally to memory. At 1,769 MB you get one full vCPU. More memory means more CPU, which can make a function run faster. Sometimes fast enough that the higher per-ms cost is offset by the shorter duration. Memory Relative CPU Typical Result 128 MB Fraction of a vCPU Cheapest per-ms, slowest 512 MB ~0.3 vCPU Often the sweet spot 1,769 MB 1 full vCPU Fast, higher per-ms cost 10,240 MB ~6 vCPUs Fastest, for CPU-bound work Caching Layers Layer Service What It Caches TTL Control Edge CloudFront Static content, API responses Cache policies, headers API API Gateway cache Endpoint responses Per-stage, per-method Application ElastiCache (Redis/Memcached) Query results, sessions Set in code Database DAX (DynamoDB only) DynamoDB reads Item + query cache TTL Caching Patterns Pattern How It Works Best For Cache-aside (lazy loading) Check cache β miss β fetch from DB β store Read-heavy, tolerates some staleness Write-through Write to cache AND DB simultaneously Consistency-sensitive reads Write-behind Write to cache, async write to DB High write throughput TTL-based Entries expire after a set time Most general-purpose caching π‘ Cache-aside is the most common pattern. The risk is a cache stampede (many simultaneous misses hitting the DB). Write-through keeps the cache fresh but adds write latency. CloudFront Cache Keys The cache key determines what makes a request unique. The fewer components in the key, the higher the cache hit rate. Cache Key Component Effect on Hit Rate No headers or query strings Highest hit rate Whitelist only what matters Balanced Forward everything Lowest hit rate (every request unique) SNS Subscription Filter Policies Filter policies let each subscriber receive only the messages it cares about, reducing downstream processing and cost. Filter Scope Filters On MessageAttributes (default) Message attribute key/value pairs MessageBody Fields inside the message body JSON Key Metrics for Finding Bottlenecks Metric Service What It Signals Duration Lambda Slow function or slow downstream call IteratorAge Lambda (Kinesis/DynamoDB) Consumer falling behind the stream ApproximateAgeOfOldestMessage SQS Consumer too slow, queue backing up Throttles Lambda Hitting concurrency limits ConsumedReadCapacityUnits DynamoDB Hot partition or under-provisioning CacheHitRate CloudFront / API Gateway Cache effectiveness ποΈ Build A Performance Optimization Lab Build a Performance Optimization Lab using the AWS Console: A Lambda function tuned across memory settings to find the cost/performance sweet spot Reserved concurrency configured to protect a downstream service API Gateway caching enabled and tested for cache hits An SNS topic with subscription filter policies routing messages selectively CloudWatch metrics queries to identify bottlenecks Prerequisites An AWS Account Part I Tune Lambda Memory for Cost and Performance Create a CPU-Bound Function 1 Open the Lambda console β Create function Function name: MemoryTuningDemo Runtime: Python 3.13 2 Click Create function 3 Paste this CPU-bound code import json import time def lambda_handler(event, context): """ A CPU-bound function that computes prime numbers. CPU-bound work benefits directly from more memory (= more CPU), making it ideal for demonstrating memory tuning. """ start = time.time() limit = event.get('limit', 500000) primes = [] for num in range(2, limit): is_prime = True for i in range(2, int(num ** 0.5) + 1): if num % i == 0: is_prime = False break if is_prime: primes.append(num) duration_ms = (time.time() - start) * 1000 return { 'statusCode': 200, 'body': json.dumps({ 'primesFound': len(primes), 'durationMs': round(duration_ms, 1), 'memoryConfigured': context.memory_limit_in_mb }) } Enter fullscreen mode Exit fullscreen mode 4 Click Deploy Run the Memory Tuning Experiment 5 Go to Configuration β General configuration β Edit β set Timeout to 1 min 0 sec β Save (so the function doesn't time out at low memory) 6 Create a test event named PrimeTest with {} 7 Now run the experiment. For each memory setting below, go to Configuration β General configuration β Edit β change Memory β Save, then run the test and record the results. You'll see duration drop sharply as memory increases, then flatten out. The point where it flattens is your sweet spot. More memory past that just costs more without speeding things up. π‘ For CPU-bound work, increasing memory often reduces total cost because the function finishes much faster. The AWS Lambda Power Tuning tool (a Step Functions state machine) automates this experiment and produces a cost/performance graph. Memory and CPU scale together. Part II Use Reserved Concurrency to Protect Downstream Services The Scenario Imagine MemoryTuningDemo calls a downstream database that can only handle 10 simultaneous connections. If Lambda scales to 100 concurrent executions, it overwhelms the database. Reserved concurrency caps this. Configure Reserved Concurrency 1 On MemoryTuningDemo, go to Configuration β Concurrency and recursion detection β Concurrency β Edit 2 Select Reserve concurrency 3 Set Reserved concurrency to 10 4 Click Save π‘ Now this function can never have more than 10 concurrent executions. Any invocations beyond that are throttled (for async sources) or receive a 429 (for synchronous sources). Observe Throttling 5 Open CloudShell and run a burst of async invocations for i in $(seq 1 50); do aws lambda invoke \ --function-name MemoryTuningDemo \ --invocation-type Event \ --payload '{"limit": 1000000}' \ /dev/null & done wait Enter fullscreen mode Exit fullscreen mode 6 Open the CloudWatch console β Metrics β Lambda β By Function Name β MemoryTuningDemo 7 Add the Throttles and ConcurrentExecutions metrics 8 You'll see ConcurrentExecutions cap at 10 and Throttles climb as excess invocations are rejected π‘ Reserved concurrency is free and acts as both a guarantee and a ceiling. It's the answer when a question situation describes a Lambda function overwhelming a downstream resource (RDS connections, a third-party API rate limit). For throttled async invocations, the events are retried. For synchronous, the caller gets a 429. Part III Enable and Test API Gateway Caching Create an API 1 Open the API Gateway console β Create API β REST API β Build 2 API name: CachingDemoAPI β Create API 3. Create resource β Resource name: products β Create resource 4 Select /products β Create method β GET β Lambda Function (proxy) β select MemoryTuningDemo β Create method Deploy to a Stage 5 Deploy API β New stage β Stage name: prod β Deploy Enable Caching on the Stage 6 In the left sidebar, click Stages β select prod 7 Under Stage details, click Edit 8 Enable Cache settings: Provision API cache: Enabled Cache capacity: 0.5 GB 9 Click Save changes (the cache takes a few minutes to provision) Enable Caching on the Method 10 With the prod stage selected, expand the resource tree and click the GET method under /products 11 Under Method settings, edit: Enable method cache: checked Cache TTL: 300 seconds 12 Save Test Cache Behaviour 13 Copy the stage Invoke URL and call the endpoint a few times: # First call β cache miss (slower, hits Lambda) curl -w "\nTime: %{time_total}s\n" https://YOUR_API/prod/products # Subsequent calls β cache hit (faster, served from cache) curl -w "\nTime: %{time_total}s\n" https://YOUR_API/prod/products curl -w "\nTime: %{time_total}s\n" https://YOUR_API/prod/products Enter fullscreen mode Exit fullscreen mode 14 The first call is slower (cache miss β Lambda runs). Subsequent calls within the TTL are much faster (served from cache, Lambda not invoked). 15 Check CloudWatch β API Gateway metrics β CacheHitCount and CacheMissCount π‘ API Gateway caching is configured per-stage and per-method. The cache key is based on the request parameters you specify. Caching reduces backend load and latency but can serve stale data within the TTL. You can force a cache bypass with the Cache-Control: max-age=0 header (if you enable that option). Part IV Optimize Messaging with SNS Filter Policies Create an SNS Topic 1 Open the SNS console β Topics β Create topic 2 Type: Standard 3 Name: order-events 4 Click Create topic Create Two SQS Queues 5 Open the SQS console β Create queue Name: premium-orders β Create queue 6 Create another: Name: all-orders β Create queue Subscribe the Queues with Filter Policies 7 Back in SNS β order-events topic β Create subscription 8 For the premium queue: Protocol: Amazon SQS Endpoint: select the premium-orders queue ARN Expand Subscription filter policy Filter policy scope: Message attributes Policy: { "orderType": ["premium"], "orderTotal": [{"numeric": [">=", 100]}] } Enter fullscreen mode Exit fullscreen mode Click Create subscription 9 Create another subscription for all-orders with no filter policy (it receives everything) Test the Filtering 10 On the order-events topic, click Publish message 11 Publish a premium order: Message body: {"orderId": "ORD-001", "amount": 250} Under Message attributes, add: Name: orderType, Type: String, Value: premium Name: orderTotal, Type: Number, Value: 250 Click Publish message 12 Publish a standard order: Message body: {"orderId": "ORD-002", "amount": 30} Message attributes: Name: orderType, Type: String, Value: standard Name: orderTotal, Type: Number, Value: 30 Click Publish message Verify the Results 13 Open SQS β all-orders β Send and receive messages β Poll for messages Both orders appear (no filter) 14 Open SQS β premium-orders β Poll for messages Only the premium order ($250) appears. The standard order was filtered out π‘ Filter policies are evaluated by SNS before delivery, so filtered-out messages never reach the subscriber thus saving SQS, Lambda, and processing costs. Without filter policies, every subscriber receives every message and must filter in code (wasteful). The default scope filters on message attributes; set the scope to MessageBody to filter on body content instead. Part V Identify Bottlenecks with CloudWatch Metrics Common Bottleneck Patterns Symptom Likely Bottleneck Fix High Lambda Duration Slow downstream call Cache the result, check X-Ray traces High IteratorAge Lambda can't keep up with the stream Increase parallelization factor, add shards SQS ApproximateAgeOfOldestMessage growing Consumer too slow Add consumers, increase batch size DynamoDB throttling Hot partition or low capacity Redesign keys, switch to on-demand API Gateway 429 Throttle limit reached Raise limits, add caching High memory usage Memory leak or large payloads Profile code, stream large data Query Lambda Performance with Logs Insights 1 Open CloudWatch β Logs β Logs Insights 2 Select /aws/lambda/MemoryTuningDemo 3 Run this query to spot memory over-provisioning: filter @type = "REPORT" | stats avg(@maxMemoryUsed/1000/1000) as avgMemMB, max(@maxMemoryUsed/1000/1000) as peakMemMB, max(@memorySize/1000/1000) as configuredMB, avg(@duration) as avgDurationMs, pct(@duration, 95) as p95Ms, pct(@duration, 99) as p99Ms Enter fullscreen mode Exit fullscreen mode 4 If peakMemMB is far below configuredMB, you're over-provisioned on memory. If p99Ms is much higher than avgDurationMs, you have tail latency worth investigating with X-Ray. Using X-Ray to Pinpoint the Slow Call A trace makes the bottleneck obvious. API Gateway: 5ms βββ Lambda: 2500ms βββ DynamoDB GetItem: 15ms βββ External API call: 2200ms β bottleneck βββ SQS SendMessage: 8ms Enter fullscreen mode Exit fullscreen mode The external API is the problem. Fixes: cache the response, make the call asynchronous (send to SQS), or add a circuit breaker to fail fast. π‘ Match the symptom to the metric. "Stream processing is delayed" β IteratorAge. "Queue is backing up" β ApproximateAgeOfOldestMessage. "Which downstream call is slow?" β X-Ray trace. ποΈ What You Built | π Exam Concepts Recap What You Built Exam Concept Ran a memory-tuning experiment across settings Memory = CPU. finding the cost/performance sweet spot Set reserved concurrency to 10 and observed throttles Reserved concurrency as guarantee + ceiling Burst-invoked to trigger throttling ConcurrentExecutions and Throttles metrics Enabled API Gateway caching per stage and method Reducing backend load and latency with caching Measured cache hits vs misses with curl timing Cache TTL behavior and CacheHitCount metric Created SNS subscriptions with filter policies Selective message delivery to reduce cost Published messages with matching/non-matching attributes MessageAttributes filter scope Queried @maxMemoryUsed and percentiles in Logs Insights Detecting over-provisioning and tail latency Mapped symptoms to metrics (IteratorAge, etc.) Choosing the right diagnostic for a bottleneck β οΈ Clean Up Protocol API Gateway β Delete CachingDemoAPI (this also removes the provisioned cache) Lambda β Delete MemoryTuningDemo SNS β Delete the order-events topic (removes subscriptions) SQS β Delete premium-orders and all-orders queues IAM β Delete the Lambda execution role CloudWatch β Delete the log group for the function Key Takeaways Reserved concurrency = guarantee + throttle (free). Provisioned concurrency = no cold starts (paid even when idle). Memory = CPU. For CPU-bound work, more memory can lower total cost by finishing faster. Lambda Power Tuning finds the sweet spot. Cache-aside is the most common caching pattern. Check cache β miss β fetch β store. CloudFront cache keys: fewer components = higher hit rate. Whitelist only what affects the response. API Gateway caching is per-stage and per-method, with a configurable TTL. SNS filter policies stop unwanted messages before delivery saving downstream cost. Default scope is message attributes. IteratorAge = stream consumer falling behind. ApproximateAgeOfOldestMessage = SQS queue backing up. X-Ray traces are the fastest way to find which downstream call is the bottleneck. Match the symptom to the metric. Additional Resources Understanding Lambda function scaling Configuring provisioned concurrency for a function Cache settings for REST APIs in API Gateway Amazon SNS message filtering Caching strategies for Memcached AWS Lambda Power Tuning ποΈ
Optimize Applications By Using AWS Services And Features | ποΈ Build A Performance Optimisation Lab
Full Article
Original Source
Read the full article at Dev →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.