Question 1 of 65
0% complete
Review your answers
0 of 65 correct
-
Question 1
Correct IncorrectWhich change reduces the empty responses and request cost with the least effort?
Add a 60-second sleep to the worker loop after every ReceiveMessage call that returns no messages. Correct answer Your answerSet the queue's ReceiveMessageWaitTimeSeconds to 20 so that each call waits for a message before it returns. Correct answer Your answerRaise MaxNumberOfMessages to 10 on every ReceiveMessage call so that each request can return more messages. Correct answer Your answerSet the queue's DelaySeconds to 20 so that the worker's ReceiveMessage calls are spaced 20 seconds apart. Correct answer Your answerExplanation
With a wait time of zero the worker short-polls: each call queries only a sample of SQS servers and returns at once, so an idle queue produces a stream of billable empty responses, and can even miss messages on unsampled servers. Setting ReceiveMessageWaitTimeSeconds to 20, the maximum, turns on long polling for every call that does not override it: SQS queries all servers and holds the request open until a message arrives or 20 seconds pass, so requests drop by orders of magnitude while a new message is still returned immediately. A 60-second sleep cuts requests but can delay a report by a full minute, which breaks the few-seconds requirement. A larger MaxNumberOfMessages helps on a busy queue but does nothing for an empty one, where every call still returns nothing. DelaySeconds makes each new message invisible for 20 seconds after it is sent; it does not space out receive calls, so it adds latency and leaves the empty polls unchanged.
-
Question 2
Correct IncorrectThe team wants API Gateway to reject missing, forged or expired tokens before any function runs and to hand the token claims to the functions. Which approach meets these requirements with the least custom code?
Create a REQUEST Lambda authorizer that downloads the user pool's JSON Web Key Set, verifies each token, and returns a simple response with the claims in its context. Correct answer Your answerTurn on IAM authorization for every route and have the app exchange its token for identity pool credentials that it uses to sign each request with SigV4. Correct answer Your answerAttach a usage plan with API keys to the stage, issue each signed-in user an API key, and have the app send that key in the x-api-key header on every request. Correct answer Your answerCreate a JWT authorizer that uses the user pool's issuer URL and the app client ID as its audience, and attach that authorizer to every route of the API. Correct answer Your answerExplanation
A JWT authorizer on an HTTP API is configuration only: API Gateway fetches the signing keys from the user pool's JWKS endpoint, checks the signature, the issuer, the audience (or the client_id claim that Cognito access tokens carry instead), expiry and any route scopes, and then passes the validated claims to the Lambda integration in the request context. A REQUEST Lambda authorizer can do the same job, but it is exactly the custom verification code the team wants to remove, now running as an extra invocation on every request. IAM authorization would force the app to add an identity pool and SigV4 signing, and the functions would see an IAM identity rather than the user pool claims. HTTP APIs do not support usage plans or API keys at all, and an API key only identifies a caller; it never authenticates one.
-
Question 3
Correct IncorrectWhich two changes scope the function's permissions to these two resources without the team writing IAM policy statements by hand?
Keep AmazonDynamoDBFullAccess and attach a permissions boundary to the function's role that allows DynamoDB actions on the ShipmentsLedger table ARN only. Correct answer Your answerReplace AmazonDynamoDBFullAccess with the DynamoDBCrudPolicy policy template under Policies, setting its TableName to a reference to ShipmentsLedger. Correct answer Your answerSet the function's Role property to the shared execution role that the platform team created for all serverless functions in the account. Correct answer Your answerReplace AmazonSQSFullAccess with a Connectors entry on the function whose destination is label-print-queue and whose permission is Write. Correct answer Your answerReplace AmazonSQSFullAccess with the AWSLambdaSQSQueueExecutionRole managed policy so that the function holds only the queue permissions it needs. Correct answer Your answerExplanation
SAM policy templates such as DynamoDBCrudPolicy take a placeholder value like TableName and expand into an IAM statement that allows the item-level read and write actions on that table and its indexes only, and a SAM connector embedded on the function, with the queue as its destination and Write as its permission, makes SAM compose a policy that includes sqs:SendMessage on that queue's ARN alone. Neither needs a hand-written statement. A permissions boundary is itself a policy that someone has to write, and it leaves the over-broad managed policy in place as the thing being trimmed. A shared execution role for every function is the opposite of least privilege, because each function inherits the others' access. AWSLambdaSQSQueueExecutionRole grants the receive and delete actions used by an event source mapping that polls a queue, on every queue, and does not grant SendMessage.
-
Question 4
Correct IncorrectWhich CloudWatch Logs Insights query returns the ten most frequent error messages for that time range?
fields @timestamp, errorCode, errorMessage | filter level = 'ERROR' | sort @timestamp desc | limit 10 Correct answer Your answerfilter level = 'ERROR' | stats count(*) as occurrences by bin(1h) | sort occurrences desc | limit 10 Correct answer Your answerfilter level = 'ERROR' | stats count_distinct(errorMessage) as occurrences by errorCode | sort occurrences desc | limit 10 Correct answer Your answerfilter level = 'ERROR' | stats count(*) as occurrences by errorMessage | sort occurrences desc | limit 10 Correct answer Your answerExplanation
Grouping the filtered error lines with stats count(*) by errorMessage produces one row per distinct message with its number of occurrences, and sorting that count in descending order with limit 10 leaves exactly the ten most frequent messages; Logs Insights discovers the JSON fields automatically, so no parse step is needed. The query that sorts by @timestamp returns the ten newest error lines, which says nothing about frequency and may show the same message ten times. Grouping by bin(1h) counts errors per hourly bucket, which is a trend over time rather than a ranking of messages. The count_distinct query reports how many different messages each errorCode produced, which ranks error codes by variety and never names a message or says how often it occurred.
-
Question 5
Correct IncorrectWhich change keeps per-account ordering while letting different accounts be processed in parallel?
Set MessageGroupId to the customer account ID on every SendMessage call made by the producers. Correct answer Your answerSet MessageDeduplicationId to the customer account ID on every SendMessage call made by the producers. Correct answer Your answerReplace the queue with an SQS standard queue and raise the event source mapping batch size to 10. Correct answer Your answerKeep the constant message group and enable high throughput mode for FIFO queues on ledger-events.fifo. Correct answer Your answerExplanation
SQS FIFO guarantees ordering within a message group, and the Lambda event source mapping processes different message groups concurrently while keeping each group in order, so using the account ID as the group ID gives one ordered lane per account and lets many accounts drain in parallel. Using the account ID as the deduplication ID would make SQS accept but never deliver any further event for that account sent within the five-minute deduplication interval, silently losing deposits and trades. A standard queue offers at-least-once delivery with best-effort ordering, so events for the same account could be applied out of order. High throughput mode raises the queue's transaction quotas, but a single message group is still delivered strictly in order one batch at a time, so the function stays at a concurrency of one.
-
Question 6
Correct IncorrectWhich two actions should the developer take so that each signed-in user can reach only the objects under that user's own prefix?
Create an IAM user for each person who signs up, and store that IAM user's access key pair in the device keychain after the person signs in to the app. Correct answer Your answerAdd a bucket policy that allows object actions on private/${aws:username}/* for the IAM role that the mobile app uses when it calls Amazon S3. Correct answer Your answerCreate a Cognito identity pool with the user pool as an identity provider, and have the app exchange its ID token for temporary credentials of the authenticated role. Correct answer Your answerAttach a policy to the identity pool's authenticated role that allows object actions on private/${cognito-identity.amazonaws.com:sub}/* in the bucket. Correct answer Your answerHave the app send the user pool access token in the Authorization header of each S3 request, so that Amazon S3 validates the signed-in user on every call. Correct answer Your answerExplanation
An identity pool turns a user pool sign-in into short-lived AWS credentials for its authenticated role, and the policy variable cognito-identity.amazonaws.com:sub resolves to the caller's identity ID at request time, so one role policy confines every user to private/identity-id/ without a per-user policy. Together these give direct, credential-free S3 access scoped per user. Creating an IAM user per person puts long-lived keys on every device and hits the IAM user quota long before the app scales. The aws:username variable exists only for IAM users, so it never resolves for a federated role session and the statement matches nothing. Amazon S3 accepts SigV4 signatures, not Cognito JWTs, so sending the access token in the Authorization header is rejected as a malformed authorization.
-
Question 7
Correct IncorrectWhich approach lets the developer exercise the handler with a realistic event without deploying any resources to AWS?
Run sam sync --watch against a development stack so that each save is deployed, then upload test objects to the bucket to trigger the function. Correct answer Your answerRun sam local start-api and send a POST request that carries the sample object key to the local endpoint that SAM opens on port 3000. Correct answer Your answerRun sam local generate-event s3 put with the bucket and key, save the output to a file, and pass that file to sam local invoke with the -e option. Correct answer Your answerRun sam local start-lambda and configure an S3 event notification on a development bucket to deliver upload events to the local endpoint. Correct answer Your answerExplanation
The sam local generate-event command prints a correctly shaped sample payload for a given service and event type, and sam local invoke runs the function once inside a Lambda-like Docker container with that payload passed through -e, so the handler sees a real S3 put event structure and nothing is created in AWS. Running sam sync --watch is useful for fast cloud iteration, but it deploys a stack to an account, which the requirement rules out. The sam local start-api command only serves functions that have Api or HttpApi events in the template, and an S3-triggered function has none, so there is no route to call. The sam local start-lambda command emulates the Lambda Invoke endpoint for SDK and CLI callers, but S3 event notifications cannot be delivered to an endpoint on a laptop.
-
Question 8
Correct IncorrectWhich design delivers every message to every consumer so that a fourth consumer can be added later without changing the producer?
Keep the single queue and have each consumer receive messages without deleting them, so the other consumers can read them later. Correct answer Your answerHave the producer call SendMessage three times for each purchase, once to a separate queue owned by each consuming team. Correct answer Your answerPublish each message to an Amazon SNS standard topic and subscribe a separate SQS queue for each consuming team to the topic. Correct answer Your answerPublish each message to an Amazon SNS standard topic and subscribe each team's HTTPS endpoint directly to the topic. Correct answer Your answerExplanation
An SNS topic with one SQS queue subscribed per consumer is the fanout pattern: SNS copies every published message into every subscribed queue, and each queue buffers its copy for up to 14 days, so a consumer that is down for hours simply drains its own queue later, and a new consumer needs only a new subscription. Receiving without deleting does not share messages; each one becomes visible again after the visibility timeout, is processed repeatedly by whichever consumer polls first, and stays until retention expires. Sending to three queues from the producer works but hard-codes the consumer list, so adding a fourth team means a producer change. Subscribing HTTPS endpoints directly gives no buffer: SNS retries an unreachable endpoint according to its delivery policy, for at most an hour, and then gives up, so a loader stopped for hours loses messages.
-
Question 9
Correct IncorrectWhich change detects the bursts within 30 seconds of their start?
Keep the metric at standard resolution and switch the alarm to the Maximum statistic over a single 60-second evaluation period. Correct answer Your answerPublish the metric with StorageResolution set to 1 and create a high-resolution alarm on it that uses a 10-second period. Correct answer Your answerPublish the metric with StorageResolution set to 1 and keep the alarm on the Average statistic over a 60-second period. Correct answer Your answerKeep the metric at standard resolution and change the period of the existing alarm to 10 seconds so it evaluates more often. Correct answer Your answerExplanation
Setting StorageResolution to 1 makes CloudWatch store the data points at one-second granularity instead of rolling them into one-minute aggregates, and a high-resolution alarm with a 10-second period then evaluates the backlog every 10 seconds, so a burst is caught well inside 30 seconds; the trade-off is that a high-resolution alarm costs more than a standard one, which operations has accepted. Switching a standard-resolution alarm to Maximum would capture the peak value, but the alarm still evaluates one-minute data points, so the alert can arrive more than a minute after the burst began. High-resolution data under a 60-second Average alarm is averaged back into the same minute that diluted the burst before. A 10-second period on a standard-resolution metric finds data only once a minute, so the alarm keeps lapsing into INSUFFICIENT_DATA rather than detecting anything sooner.
-
Question 10
Correct IncorrectThe security team accepts that a revoked token may keep working for up to 10 minutes. Which change reduces the authorizer's latency and cost with the least effort?
Configure provisioned concurrency on the authorizer function so that every authorization runs in an execution environment that is already initialized. Correct answer Your answerEnable API Gateway stage caching with a 600-second TTL on every method, so that repeated partner requests are answered without calling the backend integration. Correct answer Your answerReplace the Lambda authorizer with a Cognito user pool authorizer and migrate every partner to app clients that use the client credentials grant. Correct answer Your answerEnable authorizer result caching with a TTL of 600 seconds, so API Gateway reuses the returned policy for the same token without invoking the function. Correct answer Your answerExplanation
With authorizer caching on, API Gateway keys the cached policy on the token in the identity source header and skips the authorizer for repeat requests until the TTL expires; the TTL defaults to 300 seconds and can be raised to 3,600, so 600 seconds fits the accepted revocation window. Because the returned policy already covers every method, the cached result is safe to reuse across the API. Provisioned concurrency only removes cold starts: the function, its DynamoDB read and its 180 ms revocation call still run and bill on every request. Stage caching stores integration responses, not authorization decisions, so the authorizer still runs first on each call. Migrating every partner to Cognito client credentials is a large project when one setting solves the problem.
-
Question 11
Correct IncorrectWhich two steps make each stage invoke its matching alias with a single API definition and no changes to the function code?
Deploy the API to each stage with a deployment description that names the alias, so that API Gateway resolves the matching alias when it invokes the function. Correct answer Your answerStore the alias name in an environment variable on the function and have the handler invoke itself again under the alias that it reads from that variable. Correct answer Your answerEnable Lambda proxy integration and pass the stage name in a request header so that the Lambda service routes each request to the alias with that name. Correct answer Your answerSet the integration's function to ledger-handler:${stageVariables.lambdaAlias} and define a lambdaAlias stage variable with the value dev or prod on each stage. Correct answer Your answerRun lambda add-permission for each alias's qualified ARN so that apigateway.amazonaws.com may invoke it, scoped to the API's source ARN for that method. Correct answer Your answerExplanation
API Gateway substitutes stage variables into the Lambda integration ARN at request time, so ledger-handler:${stageVariables.lambdaAlias} resolves to the dev alias on the dev stage and the prod alias on the prod stage from one deployment. Because the URI is now dynamic, API Gateway does not add the invoke permission itself, and a resource-based permission on the unqualified function does not cover qualified alias ARNs, so each alias needs its own add-permission grant for the API Gateway service principal. A deployment description is free text that API Gateway never reads when it routes a request. Having the handler re-invoke itself under an alias changes the code and doubles every invocation and its cost. The Lambda service does not route an unqualified invocation to an alias based on a header, so a proxy integration header changes nothing.
-
Question 12
Correct IncorrectWhich change limits the invocations to the relevant events with the least operational overhead?
Add an input transformer to the rule target that removes events with a coolantTempC of 110 or below before they reach the function. Correct answer Your answerCreate an EventBridge Pipes pipe with fleet-bus as its source and a filter step on regionCode and coolantTempC that invokes the function. Correct answer Your answerSend the matched events to an SQS queue and add a filter on regionCode and coolantTempC to the function's event source mapping. Correct answer Your answerAdd numeric matching above 110 on detail.coolantTempC and prefix matching on EU- for detail.regionCode to the rule's event pattern. Correct answer Your answerExplanation
EventBridge event patterns support content filtering, so a pattern that combines a numeric comparison on coolantTempC with a prefix match on regionCode makes the rule match only the few thousand relevant events, and the bus never invokes the function for the rest. An input transformer only reshapes the payload delivered to a target after the rule has matched; it cannot drop an event, so every invocation would still happen. EventBridge Pipes reads from sources such as SQS queues, Kinesis and DynamoDB streams, Amazon MQ and Kafka; an event bus can be a pipe target but not a pipe source. Routing through an SQS queue and filtering on the event source mapping would work, but it adds a queue, a mapping and their permissions to do what the rule pattern does on its own.
-
Question 13
Correct IncorrectHow should the developer change the application code so it can write to the stream without introducing any long-lived credentials?
Call sts:GetSessionToken with the instance role's credentials, and use the returned session credentials to create the Kinesis client for the other account. Correct answer Your answerCall sts:GetFederationToken with an inline policy that names the stream ARN, and use the returned federated credentials to create the Kinesis client. Correct answer Your answerCall sts:AssumeRole on the external-writer role ARN, create the Kinesis client from the returned temporary credentials, and refresh them before they expire. Correct answer Your answerAdd the external-writer role to the instance profile beside tracker-app, so that the SDK default credential chain picks up the second role automatically at startup. Correct answer Your answerExplanation
AssumeRole is the STS operation that crosses accounts: the caller's role is trusted by external-writer, so STS returns an access key, secret key and session token that act as external-writer in account 444455556666, and the application builds its Kinesis client from them (or lets an SDK assume-role credential provider refresh them) before the session expires. GetSessionToken must be called with IAM user or root credentials, cannot be called with role credentials, and never changes the account the caller acts in. GetFederationToken is also an IAM-user operation and returns credentials scoped inside the caller's own account. An instance profile holds exactly one role, so a second role cannot be attached beside tracker-app, and the default chain would not assume it anyway.
-
Question 14
Correct IncorrectWhich approach pauses the execution until the underwriter decides with the least operational overhead?
Add a Task state that invokes an AWS Lambda function synchronously and has the function poll the web application's database for a decision. Correct answer Your answerAdd a waitForTaskToken Task state that hands the task token to the web application, which calls SendTaskSuccess or SendTaskFailure with it. Correct answer Your answerAdd a Wait state that pauses for 259,200 seconds, followed by a Choice state that reads the recorded decision from an Amazon DynamoDB table. Correct answer Your answerAdd a Task state that sends an SQS message with the sync integration pattern so the execution resumes when the web application deletes the message. Correct answer Your answerExplanation
The callback pattern (the .waitForTaskToken suffix on a service integration) pauses a Standard execution, which can run for up to a year, until something calls SendTaskSuccess or SendTaskFailure with the task token, so the approval application returns the decision directly and the workflow resumes immediately on the matching branch. A synchronous Lambda function cannot wait three days, because an invocation stops at the 15-minute maximum timeout, and polling inside it pays for idle compute. A fixed three-day Wait state always waits the full period, so an application approved in ten minutes still sits for three days. The .sync pattern is supported for job-style services such as AWS Batch, Amazon ECS, AWS Glue, AWS CodeBuild and nested Step Functions executions, not for Amazon SQS, so there is no way to wait on a message deletion.
-
Question 15
Correct IncorrectWhich approach meets these requirements without creating another stage or giving clients a new URL?
Enable canary settings on the prod stage with 5 percent of traffic, deploy the new version to the canary, and promote it once its metrics look healthy. Correct answer Your answerCreate a second stage named prod-v2 and add a weighted Route 53 record that sends 5 percent of DNS lookups to the invoke URL of that new stage. Correct answer Your answerConfigure a weighted alias on the backend Lambda function so that 5 percent of invocations reach the new function version behind the existing prod stage. Correct answer Your answerAttach a usage plan that throttles the prod stage and redeploy during a quiet window so that only a small share of clients receives the new behavior. Correct answer Your answerExplanation
A REST API stage can carry canary settings: a new deployment goes to the canary, API Gateway routes the configured percentage of requests to it, the canary writes its own CloudWatch metrics and log streams, and promoting it makes it the stage's main deployment while the URL never changes. A second prod-v2 stage is exactly what the team wants to avoid, and both stages share the same execute-api host name, so DNS weighting cannot split traffic between them. A weighted Lambda alias splits only the function code, while this release changes the validator, models and mapping templates that live in API Gateway, so those changes would reach every request or none. A usage plan throttles callers but does not route any share of traffic to a different deployment, and a redeploy changes behavior for every client at once.
-
Question 16
Correct IncorrectWhich change makes the traces searchable by clinicId without changing application code?
Replace the ADOT SDK with the AWS X-Ray SDK in the service and call putAnnotation for clinicId inside each request handler. Correct answer Your answerSearch with the filter expression metadata.clinicId = "CL-4471", because the attribute is already being recorded in each trace. Correct answer Your answerAdd clinicId to the indexed_attributes list of the awsxray exporter in the ADOT Collector configuration and redeploy the sidecar. Correct answer Your answerRaise the X-Ray sampling rule to a fixed rate of 100 percent so that every request carrying a clinicId value is recorded and indexed. Correct answer Your answerExplanation
By default the awsxray exporter translates every OpenTelemetry span attribute into X-Ray metadata, which is stored but not indexed; listing clinicId under indexed_attributes in the collector configuration turns that attribute into an annotation, which filter expressions can search, and only the sidecar configuration changes. Switching to the X-Ray SDK rewrites instrumentation code, and the X-Ray SDKs are in maintenance mode with ADOT as the recommended path. A metadata filter is not possible, because filter expressions only query annotations and built-in fields, never metadata. Sampling every request records more traces, but each one still carries clinicId as metadata, so the search still returns nothing. Setting the aws.xray.annotations span attribute in code would also work, but that is a code change.
-
Question 17
Correct IncorrectWhich change absorbs the bursts with the fewest code changes and without altering the table's capacity settings?
Keep the loop but add a fixed one-second pause before every attempt, so that every retry waits the same amount of time. Correct answer Your answerSwitch the writes to the DynamoDB Accelerator (DAX) client so that the cache cluster absorbs the burst of PutItem calls. Correct answer Your answerIncrease the function's memory to 3,008 MB so that each attempt in the retry loop completes more quickly. Correct answer Your answerRemove the custom loop and set retryMode to adaptive with a higher maxAttempts so the SDK backs off with jitter. Correct answer Your answerExplanation
The AWS SDKs already retry throttling errors with exponential backoff and random jitter, which spreads retries out until capacity frees up; the previous configuration disabled that, and the immediate loop retries hardest exactly when the table is saturated. Deleting the loop and restoring SDK retries with a higher maxAttempts fixes it in client configuration alone (adaptive mode also adds client-side rate limiting; standard mode works too). A fixed one-second pause makes every throttled caller retry in lockstep, so the retries collide again a second later. DAX is a write-through cache, so every write still consumes the table's write capacity and is throttled the same way. More memory makes each call marginally faster but adds no write capacity, so the loop simply exhausts its attempts sooner.
-
Question 18
Correct IncorrectWhich change removes the long-lived keys and limits the S3 and SQS access to invoice-render alone, with the least operational overhead?
Create an IAM role that trusts ecs-tasks.amazonaws.com and holds the bucket and queue permissions, set it as the task role, and remove the keys from the image. Correct answer Your answerAttach the bucket and queue permissions to the container instance role, so that every container on the instance can obtain them from the instance metadata service. Correct answer Your answerAdd the bucket and queue permissions to the task execution role, which the ECS agent hands to the application container so the SDK can call both services. Correct answer Your answerStore the IAM user's access key pair in Secrets Manager, inject it into the container as secrets in the task definition, and rotate the keys every 90 days. Correct answer Your answerExplanation
A task role is delivered only to the containers of that task through the ECS container credentials endpoint, which the AWS SDK default credential chain reads automatically, so invoice-render gets short-lived credentials and no other service on the same hosts inherits them. Putting the permissions on the container instance role grants them to all six services, and to anything else on the instances that can reach the metadata service. The task execution role is used by the ECS agent itself to pull images, write logs and fetch injected secrets; its credentials are not exposed to application code. Moving the IAM user's keys into Secrets Manager hides them better but leaves long-lived keys in place, plus a rotation job that someone must own.
-
Question 19
Correct IncorrectWhich change to the build step fixes the deployment with the least change to the template?
Add CAPABILITY_AUTO_EXPAND to the aws cloudformation deploy command so that the SAM transform can resolve the local folders while it expands the template. Correct answer Your answerZip each function folder and the layer folder in the build, commit the archives beside the template, and point CodeUri and ContentUri at the .zip names. Correct answer Your answerRewrite each function to use the InlineCode property so that the template carries the source directly, and remove the CodeUri and ContentUri properties. Correct answer Your answerRun sam package or aws cloudformation package with an S3 bucket and an output template file first, then deploy the packaged template that it writes. Correct answer Your answerExplanation
The package command zips each local CodeUri and ContentUri folder, uploads the archives to the named S3 bucket, and writes a copy of the template in which those local paths are replaced with S3 locations, which is what CloudFormation needs; sam deploy does the same step implicitly, which is why laptops never hit the error. CAPABILITY_AUTO_EXPAND only acknowledges that the template contains a transform that expands it, and it gives CloudFormation no way to read files on the build host. Committing zip archives still leaves local file names in the template, which CloudFormation cannot open any more than it can open folders. InlineCode suits only small functions without bundled dependencies, it would mean rewriting the function packaging, and a layer has no inline form at all.
-
Question 20
Correct IncorrectWhich approach stops the outages from consuming concurrency while resuming partner calls automatically once the API recovers?
Add a circuit breaker that tracks failures in a shared DynamoDB item and fails fast during a cooldown before a trial call. Correct answer Your answerRaise the HTTP client's retry count to five with exponential backoff so that calls made during an outage eventually succeed. Correct answer Your answerIncrease the function's timeout to 15 minutes so that slow partner calls are no longer cut off by the Lambda runtime. Correct answer Your answerConfigure provisioned concurrency on the function so that the slow invocations no longer draw from the account's concurrency pool. Correct answer Your answerExplanation
A circuit breaker turns repeated failures into an open state in which calls are rejected immediately, so the function returns the cached seat map in milliseconds instead of holding an execution environment for ten seconds; after a cooldown it lets a trial request through and closes again once the partner answers. Keeping the state in a shared store such as DynamoDB lets every execution environment see the same breaker. More retries with backoff suit brief throttling, but during a fifteen-minute outage they multiply the time each invocation is stuck and make the concurrency spike worse. A 15-minute timeout lets each stuck call live even longer. Provisioned concurrency is a pre-initialized portion of the account's concurrency, not capacity outside it, and it does nothing to make the calls finish faster.
-
Question 21
Correct IncorrectWhich two changes reduce the per-invocation latency with the fewest new resources?
Create the boto3 client and open the database connection at module level, outside the handler, and reconnect only if the connection has closed. Correct answer Your answerConfigure provisioned concurrency of 10 on an alias so that the client, the connection and the file are prepared before each request arrives. Correct answer Your answerRaise the function memory to 3,008 MB so that the TLS handshake and the 6 MB download finish faster on every invocation of the function. Correct answer Your answerStore the currency reference data in an environment variable so that Lambda loads it along with the rest of the function configuration. Correct answer Your answerKeep the reference file in a global variable or in /tmp with its download time, and fetch it from S3 again only once it is over an hour old. Correct answer Your answerExplanation
Lambda reuses a warm execution environment for later invocations, so anything created at module level during initialization survives between requests: moving the client and the database connection out of the handler removes the TLS handshake from nearly every request, provided the code reconnects when an idle connection has been closed, and caching the reference file in memory or in /tmp with a one-hour refresh removes the S3 download from all but one request per hour. Provisioned concurrency only pre-runs the initialization code, and here all of the slow work sits inside the handler, so it would still run on every request while adding cost. More memory may shave some time off each handshake and download but still repeats them on every invocation. Environment variables are capped at 4 KB in aggregate, far below a 6 MB file.
-
Question 22
Correct IncorrectAuditors want IAM itself to guarantee that a bug in a query cannot return another tenant's items. Which permissions policy on tenant-scoped-data enforces this with the least ongoing effort?
Allow the item actions on the table with a ForAllValues:StringEquals condition on dynamodb:LeadingKeys that matches ${aws:PrincipalTag/TenantId}. Correct answer Your answerAllow the item actions on the table with a condition on dynamodb:Attributes that lists only the attribute names each tenant is entitled to read or write. Correct answer Your answerAllow the item actions on the table and require the function to send a FilterExpression on TenantId with every Query and Scan request it makes. Correct answer Your answerCreate one table for each tenant, and add a policy statement naming that tenant's table ARN to the role whenever a new tenant signs up. Correct answer Your answerExplanation
The dynamodb:LeadingKeys condition key compares the partition key values a request touches with the policy, and the aws:PrincipalTag variable resolves to the session tag at request time, so one static statement lets each session read and write only items whose TenantId equals its own tag; a buggy query for another tenant fails with AccessDenied. A dynamodb:Attributes condition restricts which attribute names may be returned or written, not which items, so it isolates nothing between tenants. IAM cannot require a FilterExpression, and a filter is applied after items are read, so the protection would depend on the same code the auditors distrust. A table per tenant works but adds table sprawl, a policy edit on every sign-up and eventually the role policy size limit.
-
Question 23
Correct IncorrectWhich approach deploys the same template to both environments with the least room for operator error?
Keep two copies of template.yaml, one for each environment, with that environment's stack settings and parameter values written in as defaults. Correct answer Your answerWrap sam deploy in a shell script that exports each parameter override as an environment variable named after the parameter before it calls sam deploy. Correct answer Your answerDefine staging and prod deploy parameter tables in samconfig.toml with each stack name, Region and parameter overrides, then run sam deploy --config-env. Correct answer Your answerRun sam deploy --guided before every deployment and answer each prompt with the stack name, Region and parameter values for the target environment. Correct answer Your answerExplanation
The SAM CLI reads named environments from samconfig.toml, so tables such as [staging.deploy.parameters] and [prod.deploy.parameters] hold each stack name, Region, bucket and parameter_overrides, and sam deploy --config-env prod applies exactly that set from one template that is checked into source control. Two copies of the template drift apart as soon as someone fixes a resource in only one of them. The SAM CLI does not read parameter overrides from arbitrarily named environment variables, so the wrapper script would pass nothing and the stack would fall back to the template defaults. Running a guided deploy every time reintroduces the manual typing that caused the incident, and by default it writes the answers into the default environment of the config file.
-
Question 24
Correct IncorrectWhich two steps make API Gateway reject the invalid bodies?
Create an application/json model whose JSON Schema requires destinationPostcode and declares weightKg as a number. Correct answer Your answerAdd a mapping template to the integration request that strips every property the expected body schema does not define, before the function is invoked. Correct answer Your answerAssociate an AWS WAF web ACL with the stage that blocks any request whose body is larger than 8 KB in size. Correct answer Your answerSet the method's request validator to one that validates the body, and set the model as the method's request model for application/json. Correct answer Your answerAttach a REQUEST-type Lambda authorizer that inspects the body and returns a Deny policy when a required field is missing. Correct answer Your answerExplanation
API Gateway REST APIs validate request bodies against a model written in JSON Schema draft 4, but only when the method also has a request validator that validates the body and the model is set as the method's request model for the content type; together they reject a nonconforming body with 400 Bad Request before the integration is called. A mapping template transforms the payload sent to the backend and never rejects a request, so the invalid body would still reach the function. A WAF size rule blocks large requests, not small well-formed ones with a missing field or a wrong type. A REQUEST Lambda authorizer receives headers, query strings, path parameters, stage variables and request context, but not the request body, and it would still be an extra function to write and pay for.
-
Question 25
Correct IncorrectWhat should the developer do so that quote-builder can call the API while following least privilege?
Grant the execution role execute-api:Invoke on that method's ARN, and sign each request with Signature Version 4 using the role credentials for the execute-api service. Correct answer Your answerCreate an API key, associate it with a usage plan for the stage, and have the function send that key in the x-api-key header of every request to the API. Correct answer Your answerGrant the execution role apigateway:GET on the API's resources, and send the execution role ARN in the Authorization header of every request that it makes to the API. Correct answer Your answerGrant the execution role execute-api:Invoke on that method's ARN, and let API Gateway read the caller's role from the Lambda invocation context. Correct answer Your answerExplanation
IAM authorization means API Gateway evaluates the SigV4 signature on the request, identifies the signing principal and checks that it is allowed execute-api:Invoke on the specific method ARN, so the role needs that permission scoped to GET /prices/* and the client must sign with the role's temporary credentials for the execute-api service. An API key is used for usage plans and throttling, not for authentication, and an IAM-authorized method still rejects the unsigned request. The apigateway:GET action governs the management API that reads API definitions, not invoking them, and a role ARN in a header is not a credential. Granting execute-api:Invoke alone is not enough either: API Gateway knows nothing about the caller's role unless the request is signed.
-
Question 26
Correct IncorrectWhich change makes clients receive the quote with the fewest changes?
Raise the function timeout and set the API Gateway integration timeout to 29 seconds so the response is not cut off. Correct answer Your answerSwitch the method to a non-proxy Lambda integration and add integration and method responses that map the result. Correct answer Your answerAdd a Content-Type header of application/json to the method response configuration in API Gateway. Correct answer Your answerReturn a dict with statusCode 200, a headers map, and a body set to json.dumps of the result. Correct answer Your answerExplanation
With a Lambda proxy integration API Gateway passes the function's return value straight through, so it must have the proxy response shape: an integer statusCode, optional headers, and a body that is a string. A bare dictionary has no statusCode and its data is not a string body, so API Gateway reports a malformed proxy response and returns 502; returning statusCode 200 with json.dumps of the result as the body fixes it in one line. The timeouts are irrelevant, because the function finishes in 80 ms and an integration timeout would produce 504, not 502. A non-proxy integration with mapping and method responses would also work, but it is a much larger reconfiguration than a handler change. Method response settings do not reshape a proxy integration's output, so a header defined there leaves the malformed response unchanged.
-
Question 27
Correct IncorrectWhich approach meets these requirements without publishing new function code or versions?
Store the flag in a Lambda environment variable and publish a new function version with weighted alias routing whenever the flag value has to change. Correct answer Your answerStore the flag in a Parameter Store parameter that the function reads on every invocation, with an EventBridge rule that resets it when the alarm fires. Correct answer Your answerCreate an AWS AppConfig feature flag, deploy it with a linear strategy and the alarm as an environment monitor, and read it through the AppConfig extension. Correct answer Your answerStore the flag in a DynamoDB item and enable DynamoDB Streams so that a second function reverts the item whenever the alarm changes its state. Correct answer Your answerExplanation
AWS AppConfig deploys a feature flag configuration to an environment using a deployment strategy that controls growth over time, such as a linear rollout over 30 minutes, and it watches the CloudWatch alarms registered as monitors on that environment, rolling the configuration back automatically if one fires during the deployment or bake time. The AppConfig Agent Lambda extension caches the flag locally, so the code reads it without new versions. An environment variable change requires publishing a new version, which the requirement rules out. A Parameter Store value flips for every request at once, so there is no gradual rollout, and the revert logic is custom. A DynamoDB item with a stream-driven reverter is also custom code, adds a read to each invocation, and still offers no gradual exposure.
-
Question 28
Correct IncorrectWhich change is most likely to cut the duration with little or no increase in cost per invocation?
Lower the memory to 256 MB, because the function never uses more than 180 MB and Lambda bills for the memory that is allocated. Correct answer Your answerRaise the memory toward 1,769 MB and measure with AWS Lambda Power Tuning, because Lambda allocates CPU in proportion to memory. Correct answer Your answerRaise the function timeout to 15 minutes and enable provisioned concurrency so that each invocation receives a larger CPU share. Correct answer Your answerIncrease the ephemeral /tmp storage to 10,240 MB so that Pillow can spill its intermediate image buffers to local disk faster. Correct answer Your answerExplanation
Lambda assigns CPU in proportion to configured memory, reaching the equivalent of one full vCPU at 1,769 MB, so a single-threaded CPU-bound function at 512 MB is starved of compute rather than memory; raising memory shortens the duration roughly in step with the added CPU, and because billing is memory multiplied by duration the cost per invocation stays about flat or falls, which Power Tuning confirms with real measurements. Halving the memory to 256 MB also halves the CPU, roughly doubling the duration, so it saves nothing and makes the function slower. A longer timeout only allows a slow invocation to run longer, and provisioned concurrency removes initialization latency without granting more CPU. Larger /tmp storage helps disk-heavy work, not a CPU-bound resize that fits comfortably in memory.
-
Question 29
Correct IncorrectHow should the developer encrypt the documents under the KMS key while keeping the number of KMS requests to a minimum?
Split each document into 4 KB chunks, call Encrypt on every chunk with the key, and store the resulting ciphertext chunks together in their original order in S3. Correct answer Your answerRequest a service quota increase for the Encrypt plaintext size so that the key accepts payloads of up to 4 MB, then keep calling Encrypt on each document. Correct answer Your answerCall GenerateDataKey, encrypt the document locally with the plaintext data key, store the encrypted data key beside the ciphertext, and discard the plaintext key. Correct answer Your answerCall GenerateRandom once for a 256-bit value, store it in a Lambda environment variable, and use it to encrypt every document locally with AES-GCM. Correct answer Your answerExplanation
Envelope encryption is the pattern KMS is built for: one GenerateDataKey request returns a plaintext data key and the same key encrypted under alias/visit-notes, the application encrypts the 2 MB document locally with AES-GCM, and only the small encrypted data key needs a Decrypt call later. The AWS Encryption SDK packages exactly this flow. Chunking a 2 MB document into 4 KB pieces costs about 500 Encrypt requests per document and quickly runs into KMS request quotas. The 4,096-byte plaintext limit on Encrypt is fixed, not an adjustable quota. A random value stored in an environment variable is a single static key that never touches KMS again, so access to it is neither controlled by the key policy nor logged per use in CloudTrail.
-
Question 30
Correct IncorrectWhich change gives each application its own read throughput with the lowest propagation delay?
Double the stream to 16 shards with UpdateShardCount so the read throughput that the five applications share is doubled. Correct answer Your answerIncrease the stream's data retention period to seven days so that applications that fall behind can catch up later. Correct answer Your answerRegister each application as an enhanced fan-out consumer and switch it from polling to SubscribeToShard. Correct answer Your answerRaise the Limit parameter on every GetRecords call to 10,000 records so that each request returns more data per call. Correct answer Your answerExplanation
Shared-throughput consumers split each shard's 2 MB per second of reads and its five GetRecords calls per second, so a fifth poller pushes all of them over the limit. An enhanced fan-out consumer gets its own dedicated 2 MB per second per shard, and records are pushed over HTTP/2 through SubscribeToShard with a typical propagation delay of about 70 ms, independent of the other registered consumers. Resharding to 16 shards raises the shared limits, but every application still competes for them and still pays the polling delay. A longer retention period only lets laggards recover later; it does not stop them from lagging. A larger Limit returns more records per call but cannot exceed the 2 MB per second shard read limit, so bigger reads simply hit it sooner.
-
Question 31
Correct IncorrectWhich deployment policy meets these requirements while keeping the same environment and URL?
Immutable, which launches a full set of new instances in a temporary Auto Scaling group and terminates only those new instances if the deployment fails. Correct answer Your answerRolling with additional batch, which launches one extra batch of instances first and then updates the existing instances in batches until all are done. Correct answer Your answerRolling, which takes one batch of existing instances out of service at a time, deploys the new version to it, and returns it to the load balancer. Correct answer Your answerAll at once, which deploys the new version to every existing instance in the environment simultaneously and restarts the application server on each. Correct answer Your answerExplanation
An immutable deployment never touches the running instances: Elastic Beanstalk launches a complete set of new instances with the new version in a temporary Auto Scaling group, moves them into the environment only once they pass health checks, and on failure terminates just the new instances, so capacity stays full and rollback is quick and safe. Rolling with additional batch preserves capacity, but it updates the original instances in place, so a failure part-way leaves a mix of versions and recovery is another deployment. Rolling removes a batch from service at a time and therefore reduces capacity, with the same mixed-version failure mode. All at once updates every instance together, causing a brief outage and leaving no healthy original instances if the new version is broken.
-
Question 32
Correct IncorrectWhich change guarantees that either all three writes take effect or none do, with the least custom code?
Combine the three writes into a single BatchWriteItem request so that DynamoDB applies them to both tables together. Correct answer Your answerEnable DynamoDB Streams on Wallets and have a second function reverse any debit that has no matching credit after a minute. Correct answer Your answerRead both wallet items with strongly consistent reads before each write, and retry any write that fails until it succeeds. Correct answer Your answerSend one TransactWriteItems request with Update actions for both wallets, a condition on the sender's balance, and a ledger Put. Correct answer Your answerExplanation
TransactWriteItems groups up to 100 actions across one or more tables in the same account and Region into a single all-or-nothing operation, so the conditional debit, the credit and the ledger Put either all commit or, if the balance condition fails or the request conflicts, all are canceled with a TransactionCanceledException that lists the reason per action. BatchWriteItem is not atomic: some writes can succeed while others come back as UnprocessedItems, and it supports only puts and deletes with no condition expressions, so it cannot even express the conditional debit. A stream-driven compensator leaves balances wrong until it runs. Strongly consistent reads show the latest data but give no atomicity, and retrying from code that has already timed out cannot finish the transfer.
-
Question 33
Correct IncorrectWhich bucket configuration makes Amazon S3 reject every request to the bucket that is not sent over TLS, with the least effort?
Enable default encryption with SSE-KMS on the bucket so that every object is encrypted under a KMS key before Amazon S3 writes it to storage. Correct answer Your answerAdd a bucket policy statement that denies all S3 actions on the bucket and its objects for every principal when aws:SecureTransport is false. Correct answer Your answerAdd a bucket policy statement that allows s3:PutObject for the upload roles only when aws:SecureTransport is true for the incoming request to the bucket. Correct answer Your answerAdd a bucket policy statement that denies s3:PutObject unless the request includes the x-amz-server-side-encryption header with aws:kms. Correct answer Your answerExplanation
An explicit Deny conditioned on aws:SecureTransport being false overrides any Allow, whether it comes from an identity-based policy or the bucket policy, so every plain HTTP request to the bucket or its objects is refused no matter which role sends it. Default SSE-KMS encryption protects objects at rest and says nothing about how the request traveled. An Allow conditioned on secure transport does not block anything, because the roles in the same account are already allowed by their identity-based policies and an unmet Allow simply does not apply. Requiring the server-side encryption header again concerns encryption at rest; a script can send that header over plain HTTP and the request would still be accepted.
-
Question 34
Correct IncorrectWhich change stops the unwanted invocations with the least code and operational overhead?
Keep the subscription as it is and add a check at the top of the handler that returns immediately unless eventType is RefundIssued. Correct answer Your answerCreate a second SNS topic for refunds and change the publisher so that it also sends every RefundIssued event to the new topic. Correct answer Your answerAttach the filter policy {"eventType": ["RefundIssued"]} to the subscription, with the filter policy scope set to MessageAttributes. Correct answer Your answerSubscribe an Amazon SQS queue to the topic instead and have the function read from the queue with an event source batch size of 10. Correct answer Your answerExplanation
A subscription filter policy is evaluated by SNS before delivery, so with a policy matching eventType RefundIssued on the message attributes, SNS delivers only refund events to refund-ledger and the other 97 percent never invoke the function; it is a configuration change on the subscription with no code involved. An early return in the handler still pays for every invocation and still consumes concurrency, it only makes each wasted call shorter. A dedicated refunds topic works but requires a publisher code change and another topic to operate. Moving the function behind an SQS queue with a batch size of 10 reduces the number of invocations, yet the function still receives and discards every unwanted message, now with a queue to manage as well.
-
Question 35
Correct IncorrectWhich action restores the previous behavior of the prod stage with the fastest recovery and without rebuilding or redeploying anything?
Change the prod stage's active deployment back to the previous deployment ID, from its deployment history or with update-stage on /deploymentId. Correct answer Your answerRevert the commit in the Git repository and let the pipeline rebuild the project and run its full deployment to the prod stage once again. Correct answer Your answerDelete the prod stage and create it again from the previous deployment, then reapply its stage variables, throttling and logging settings. Correct answer Your answerRe-import the OpenAPI file from the previous release in overwrite mode and create a new deployment of that imported definition to prod. Correct answer Your answerExplanation
A REST API deployment is a snapshot of the API's methods, integrations and mapping templates, and a stage simply points at one, so changing the stage's active deployment from its Deployment history tab, or running update-stage with a replace patch on /deploymentId, puts the earlier snapshot back in service immediately without rebuilding anything. Reverting the commit and letting the pipeline run is a sound long-term fix, but it waits for a full build and deployment while every quote request keeps failing. Deleting and recreating the stage takes the prod URL offline until the new stage exists and discards its stage settings, which must be rebuilt by hand. Re-importing an older OpenAPI file overwrites the current API definition and still needs a new deployment, which is slower and may restore a file that never matched what was live.
-
Question 36
Correct IncorrectWhich event source mapping configuration meets these requirements?
Configure an SQS dead-letter queue in the function's asynchronous invocation settings so that failed records are moved off the stream. Correct answer Your answerRaise the ParallelizationFactor to 10 so that each shard is processed by several concurrent batches while the bad record is retried. Correct answer Your answerSet MaximumRetryAttempts to 0 so that a failing batch is skipped after its first error and the shard moves on to the next batch. Correct answer Your answerTurn on BisectBatchOnFunctionError, set MaximumRetryAttempts to 3, and add an on-failure destination that sends to an SQS queue. Correct answer Your answerExplanation
By default a stream event source mapping retries a failing batch until the records expire, so one poison record holds its shard in place. BisectBatchOnFunctionError splits a failed batch in half repeatedly, so the valid halves succeed and the bad record ends up isolated; MaximumRetryAttempts (or MaximumRecordAgeInSeconds) bounds the retries, after which Lambda discards the record and moves on, and the on-failure destination receives the shard ID, sequence-number range and error context for the discarded batch (metadata only for an SQS destination). A function-level dead-letter queue applies only to asynchronous invocations, and an event source mapping invokes the function synchronously, so nothing would reach it. A higher ParallelizationFactor adds concurrency per shard, but the bad record is still retried indefinitely. Zero retries skips the whole batch of 500 on its first error, discarding the valid records with it and leaving no record of what was lost.
-
Question 37
Correct IncorrectWhich approach meets the contract with the least custom cryptographic code?
Upload the files over HTTPS to a bucket whose default encryption uses SSE-KMS with the firm's customer managed key, so that S3 encrypts each object. Correct answer Your answerUpload the files to a bucket that uses dual-layer server-side encryption (DSSE-KMS) with the firm's customer managed key for every object. Correct answer Your answerEncrypt each file in the application with the AWS Encryption SDK and a KMS keyring for the firm's key, then upload the encrypted message to S3. Correct answer Your answerCall the KMS Encrypt operation on each file from the application with the firm's key, and upload the ciphertext blob that KMS returns to S3. Correct answer Your answerExplanation
The AWS Encryption SDK performs client-side envelope encryption for the application: the KMS keyring obtains a data key under the firm's KMS key, the SDK encrypts the file locally and emits a portable encrypted message that carries the encrypted data key, so only ciphertext ever leaves the workstation and no hand-written cryptography is involved. SSE-KMS encrypts at rest inside Amazon S3, which means S3 receives the plaintext (protected only by TLS in transit), breaking the contract. DSSE-KMS adds a second server-side layer but has the same flaw: the encryption still happens in S3 after the plaintext arrives. Calling KMS Encrypt directly fails for these files, because that operation accepts at most 4,096 bytes of plaintext.
-
Question 38
Correct IncorrectWhich change makes CloudFront keep a separate cached copy for each language while still serving cached responses from the edge?
Create a custom origin request policy that forwards Accept-Language so the header reaches the load balancer on every cache miss. Correct answer Your answerAttach a custom cache policy that includes the Accept-Language header in the cache key while keeping the current TTL settings. Correct answer Your answerSet the default, minimum and maximum TTLs in the cache policy to 0 seconds so that CloudFront sends every request to the origin. Correct answer Your answerConfigure the load balancer targets to add a Vary: Accept-Language response header so that CloudFront stores one copy per language. Correct answer Your answerExplanation
Only values in the cache key make CloudFront store separate objects, and a cache policy that includes Accept-Language yields one cached copy per header value, three here; headers in a cache policy are also forwarded to the origin automatically, so the origin still sees the language. A custom origin request policy only controls what reaches the origin on a miss, which AllViewer already does, and values it adds are never part of the cache key, so the first language cached keeps being served to everyone. Zero TTLs stop the wrong copy from being served by disabling caching, which defeats the requirement to serve from the edge. CloudFront does not split its cache on a Vary response header, apart from its own handling of Accept-Encoding, so Vary changes nothing.
-
Question 39
Correct IncorrectWhich change makes CodeDeploy fail the deployment on any instance where the worker does not become healthy after it starts?
Add a BeforeInstall hook to appspec.yml that runs a script which polls localhost:8081/health and exits with a nonzero code when the check fails. Correct answer Your answerAdd an ApplicationStop hook to appspec.yml that runs a script which polls localhost:8081/health and exits with a nonzero code when the check fails. Correct answer Your answerAdd a post_build command to the CodeBuild buildspec that starts the worker inside the build container and fails the build when the health check fails. Correct answer Your answerAdd a ValidateService hook to appspec.yml that runs a script which polls localhost:8081/health and exits with a nonzero code when the check fails. Correct answer Your answerExplanation
ValidateService is the last lifecycle event of an EC2 in-place deployment, running after ApplicationStart, so a script there sees the newly started worker, and a nonzero exit code or a timeout fails the deployment for that instance, which can trigger an automatic rollback if the deployment group enables one. BeforeInstall runs before the new revision is copied into place and before the worker has started, so the check would test the old process or nothing. ApplicationStop runs first and uses the scripts from the previously deployed revision, so a new check would not take effect until the next deployment and would still run before the new code starts. A post_build check in CodeBuild tests the artifact in a build container, not the real start-up on each instance, so environment-specific crashes would still slip through.
-
Question 40
Correct IncorrectWhich two changes make only the failed messages return to the queue while keeping the batch size of 10?
Reduce the event source mapping's batch size to 1 so that each failing message is retried on its own. Correct answer Your answerAdd ReportBatchItemFailures to the FunctionResponseTypes setting of the event source mapping for the queue. Correct answer Your answerSet the maxReceiveCount of the queue's redrive policy to 1 so that a failed batch moves to the dead-letter queue. Correct answer Your answerConfigure an on-failure destination on the event source mapping that sends failed batches to a second SQS queue. Correct answer Your answerReturn batchItemFailures with the itemIdentifier of each failed message instead of raising an exception. Correct answer Your answerExplanation
Partial batch responses need both halves: the event source mapping must list ReportBatchItemFailures in FunctionResponseTypes, and the handler must return a batchItemFailures array with the messageId of each failed record as its itemIdentifier. Lambda then deletes the successful messages and only the listed ones become visible again; if the handler raises an exception instead, the whole batch is still treated as failed. A batch size of 1 isolates failures but abandons the batch size the scenario requires and multiplies invocations tenfold. A maxReceiveCount of 1 sends the entire failed batch, valid payouts included, to the dead-letter queue on the next receive. On-failure destinations on event source mappings apply to stream and Kafka sources; for an SQS source, failed messages are handled by the queue's own redrive policy.
-
Question 41
Correct IncorrectThe security team wants KMS itself to refuse such a cross-tenant decryption and wants each KMS call in AWS CloudTrail to show which tenant it served. Which two actions meet these requirements?
Pass an encryption context of tenantId set to the tenant's ID on every GenerateDataKey call, and pass the identical encryption context on every Decrypt call for that tenant. Correct answer Your answerCreate a separate alias for each tenant that points to the shared key, because KMS binds every ciphertext to the alias that was named in the request that originally created it. Correct answer Your answerAdd a key policy condition that allows GenerateDataKey and Decrypt only when kms:EncryptionContext:tenantId equals ${aws:PrincipalTag/tenantId} for the calling role. Correct answer Your answerAdd a key policy condition with ForAllValues:StringEquals on kms:EncryptionContextKeys that lists tenantId as the only encryption context key each role may send. Correct answer Your answerStore the tenant ID in an S3 object tag beside each encrypted document, and have the pipeline compare that tag with its own tenant before it calls Decrypt. Correct answer Your answerExplanation
An encryption context is authenticated additional data: KMS binds it to the ciphertext, Decrypt succeeds only when the identical, case-sensitive context is supplied, and the context appears in plaintext in the CloudTrail record of each call. Adding a key policy condition that ties kms:EncryptionContext:tenantId to the caller's own tenantId tag then stops a role from even asking for another tenant's context, so a misrouted job fails inside KMS, provided no IAM policy on the tenant roles grants kms:Decrypt on the key without the same condition. Aliases are only friendly names; ciphertext is bound to the key, not to the alias used. A ForAllValues test on kms:EncryptionContextKeys checks key names, not values, and also matches requests that carry no context at all, so t-2207 could still send tenantId t-1184. Comparing an S3 tag in application code is the same kind of check the misrouted job already bypassed; KMS would never enforce it.
-
Question 42
Correct IncorrectWhich approach removes the duplicated dependencies with the least operational overhead?
Upload the shared libraries to an Amazon S3 bucket and download them into /tmp from each function's initialization code. Correct answer Your answerPublish the shared libraries as a Lambda layer under a python directory and add the layer to each function. Correct answer Your answerStore the shared libraries on an Amazon EFS file system and mount the file system on every function at /mnt/libs. Correct answer Your answerMove the shared libraries into a Git submodule that is copied into each function's source folder at build time. Correct answer Your answerExplanation
A Lambda layer is a .zip archive that Lambda extracts into /opt, and for Python the contents of its python directory are added to the import path, so the shared libraries are published once and each function references a layer version instead of bundling its own copy. Layer versions are immutable, so a rates-common fix becomes one new layer version, which SAM can roll out to all 34 functions through a single shared resource reference. Downloading from S3 into /tmp needs custom loader code and adds the download to every cold start. EFS mounts require the functions to be attached to a VPC, which the team ruled out, and they add a file system to manage. A Git submodule removes duplication from the source tree only; every package still bundles its own 18 MB copy and must be rebuilt for each fix.
-
Question 43
Correct IncorrectWhich approach lets the function run on Lambda while keeping every dependency packaged in the function's deployment artifact?
Split the dependencies across five Lambda layers so that each layer archive stays below 50 MB zipped and attach all five layers to the function. Correct answer Your answerUpload the .zip archive to an S3 bucket and create the function from the S3 object, which raises the unzipped package limit to 10 GB. Correct answer Your answerBuild a container image from the AWS Lambda base image for Python 3.13, push it to Amazon ECR, and create the function from that image. Correct answer Your answerDownload the libraries and model files from S3 into /tmp during initialization after raising the function's ephemeral storage to 10,240 MB. Correct answer Your answerExplanation
A Lambda function packaged as a container image can be up to 10 GB uncompressed, so building from the AWS base image for Python 3.13, pushing it to Amazon ECR and creating the function from the image keeps all 2.1 GB of dependencies inside the deployment artifact. Splitting dependencies across layers does not help, because the 250 MB unzipped limit applies to the function code and all of its layers combined. Uploading the archive through S3 only lifts the 50 MB direct-upload limit on the zipped file, and the 250 MB unzipped limit still applies. Downloading into /tmp at initialization can be made to work, but it moves the dependencies out of the deployment artifact, which the requirement rules out, and adds a large download to every cold start.
-
Question 44
Correct IncorrectWhich approach meets the standard without re-encrypting existing records or changing the application, with the least operational overhead?
Create a new KMS key every 180 days, repoint the alias to it, and run a batch job that re-encrypts every stored record under the newly created key. Correct answer Your answerSchedule a Lambda function every 180 days that calls RotateKeyOnDemand on the key, because automatic rotation only runs on a fixed yearly schedule. Correct answer Your answerEnable automatic rotation with a 180-day period, then re-encrypt the existing records, because KMS deletes the old key material after each rotation. Correct answer Your answerEnable automatic rotation with a 180-day rotation period; KMS keeps all earlier key material and uses it to decrypt older ciphertext automatically. Correct answer Your answerExplanation
Automatic rotation for a customer managed key accepts a custom rotation period between 90 and 2,560 days (365 by default), so a 180-day period meets the standard with one setting; the key ID and ARN never change, and KMS retains every previous version of the key material so data keys encrypted years ago still decrypt without any change. Creating a new key and re-encrypting the archive every 180 days is a recurring project, and the ARN-based configuration would still point at the old key. A scheduled on-demand rotation would work, but it rests on the outdated idea that automatic rotation is fixed at one year and adds a function to maintain. KMS never deletes earlier key material on rotation, so re-encrypting the records is unnecessary work.
-
Question 45
Correct IncorrectWhich solution delivers microsecond read latency with the fewest code changes?
Switch the table to on-demand capacity mode so that DynamoDB scales its read throughput automatically to follow demand. Correct answer Your answerCreate a DynamoDB Accelerator cluster and replace the DynamoDB client with the DAX client, keeping the existing GetItem calls. Correct answer Your answerAdd an Amazon ElastiCache cluster and implement cache-aside reads with explicit invalidation on every write in the service. Correct answer Your answerAdd a global table replica in the Region closest to most players and point the read path of the service at that replica. Correct answer Your answerExplanation
DAX is an in-memory, write-through cache built for DynamoDB that serves eventually consistent reads from cache in microseconds, and its client is API-compatible with the DynamoDB client, so the service swaps the client and keeps its GetItem calls unchanged. On-demand capacity mode changes how throughput is provisioned and billed, but every read still goes to DynamoDB at millisecond latency. ElastiCache can also return cached data in microseconds, but the team would have to write cache-aside logic, choose keys and TTLs, and invalidate entries on every write, which is far more code. A global table replica only moves the data closer to some players; reads against it are still DynamoDB reads measured in milliseconds.
-
Question 46
Correct IncorrectWhich change protects the database with the least operational overhead?
Set reserved concurrency of 40 on the function so that excess events are throttled and retried later by Lambda. Correct answer Your answerConfigure provisioned concurrency of 40 on an alias of the function and point the S3 notification at that alias. Correct answer Your answerPlace an Amazon RDS Proxy in front of the database and change the function to connect through the proxy endpoint. Correct answer Your answerRequest a lower Regional concurrent executions quota of 40 for the account through Service Quotas. Correct answer Your answerExplanation
Reserved concurrency is both a guarantee and a ceiling, so at 40 the function can never hold more than 40 database connections. Because S3 invokes the function asynchronously, events that arrive while it is at its limit are throttled and kept in Lambda's internal queue, which retries them for up to the six-hour default maximum event age, so the backlog simply drains over the following minutes. Provisioned concurrency only keeps execution environments initialized; it is not a cap, and the function scales past it on demand. RDS Proxy pools connections only for Amazon RDS and Aurora databases, not for PostgreSQL that runs on EC2. Service Quotas takes requests to raise the account-level concurrency quota, not to lower it, and an account-wide limit would throttle every function in the account rather than this one.
-
Question 47
Correct IncorrectWhich change produces a working deployment package without changing the laptop's operating system or setting up a separate build server?
Run sam build with --use-container so that the dependencies are installed and compiled inside a Lambda build image for python3.13. Correct answer Your answerMove the compiled dependency into a Lambda layer that is built on the laptop, attach the layer to the function, and deploy the function again. Correct answer Your answerChange the function's architecture to arm64 so that Lambda can load compiled modules regardless of the platform that the module was built on. Correct answer Your answerDeploy with sam sync --code so that only the handler code is uploaded and the Lambda service installs the dependencies from requirements.txt. Correct answer Your answerExplanation
With --use-container, sam build runs the dependency installation inside a container image that behaves like the Lambda environment for the function's runtime and architecture, so the C extension is compiled for Amazon Linux on x86_64 and imports correctly once deployed; Docker Desktop on the laptop is all it needs. Building a layer on the same laptop moves the Windows-compiled module into another archive without changing what it was compiled for. Switching to arm64 makes the mismatch worse, because Lambda loads native code only when it matches both the operating system and the processor architecture. Lambda never installs packages from requirements.txt at deploy or run time, so uploading only the handler code with sam sync --code leaves the module missing entirely.
-
Question 48
Correct IncorrectWhich approach lets the browser upload the video with the least development effort?
Have upload-ticket use the SDK to create a presigned PUT URL for a single object key that expires in 15 minutes, and have the browser PUT the file straight to that URL. Correct answer Your answerHave upload-ticket create a presigned PUT URL that expires in 7 days so that a candidate can retry the upload later, and sign it with the function execution role credentials. Correct answer Your answerSend the video through an API Gateway REST API that uses an S3 service integration to write the request body to the bucket under the candidate's object key. Correct answer Your answerAdd a bucket policy that allows s3:PutObject for all principals on the uploads/ prefix, and have the browser send an unsigned PUT request for the candidate's key. Correct answer Your answerExplanation
A presigned URL carries a signature made with the backend's credentials for one operation on one key, so the browser can PUT that single object directly to Amazon S3 for the 15 minutes requested without ever holding credentials; the bucket only needs a CORS rule allowing PUT from the site's origin. A 7-day expiry breaks the 15-minute requirement, and it would not hold anyway: a URL signed with temporary credentials such as a Lambda execution role's stops working when those credentials expire, whatever expiry was requested, and only IAM user credentials reach the 7-day maximum. Routing the video through API Gateway fails because its request payload limit is 10 MB, far below 300 MB. A bucket policy that allows anonymous PutObject makes the prefix publicly writable, which no time or key limit can repair.
-
Question 49
Correct IncorrectWhich design change removes the throttling while still supporting the session-based reads?
Switch the table from on-demand to provisioned mode and set a write capacity well above 1,500 units per second. Correct answer Your answerMake a high-cardinality attribute such as sessionId the partition key, with eventTime as sort key, in a new table. Correct answer Your answerAdd a global secondary index that uses sessionId as its partition key and keep eventDate as the table's partition key. Correct answer Your answerPlace a DynamoDB Accelerator (DAX) cluster in front of the table so that the cluster absorbs the burst of writes. Correct answer Your answerExplanation
A single partition key value is served by one partition, which supports up to 1,000 write units per second, so putting all of a day's writes under one eventDate value creates a hot partition no matter how much table capacity exists. Keying on sessionId spreads writes across many partitions and matches the session-based read pattern; because a table's partition key cannot be changed, that means a new table and a migration. Provisioned mode raises table capacity but not the per-partition limit, so the hot key still throttles. A global secondary index adds a second write for every item and leaves the base table's hot key exactly where it was. DAX is a write-through cache, so every write still lands on the same hot partition.
-
Question 50
Correct IncorrectWhich approach meets the requirement with the least ongoing maintenance?
Add a trigger to every deployment group that publishes DeploymentSuccess and DeploymentFailure events to an Amazon SNS topic. Correct answer Your answerCreate an Amazon EventBridge rule for CodeDeploy deployment state-change events in the SUCCESS or FAILURE state, targeting SNS. Correct answer Your answerCreate an AWS CloudTrail metric filter on CreateDeployment API calls with a CloudWatch alarm that notifies an Amazon SNS topic. Correct answer Your answerSchedule a Lambda function every five minutes that calls ListDeployments and GetDeployment and publishes outcomes to SNS. Correct answer Your answerExplanation
CodeDeploy emits a CodeDeploy Deployment State-change Notification event to EventBridge for every deployment, so one rule matching the SUCCESS and FAILURE states for any application and any deployment group, with an SNS topic and email subscriptions as its target, covers all 14 groups and every group created later with no further work. Deployment group triggers do send these events to SNS, but they are configured per group, so every new group needs its own trigger and a forgotten one goes silent. A metric filter on CreateDeployment only sees the API call that starts a deployment, never whether it succeeded or failed. A polling function is custom code to write and maintain, and it reports outcomes up to five minutes late.
-
Question 51
Correct IncorrectWhich approach meets these requirements with the least ongoing effort?
Connect each feature branch to the app in the Amplify console as a new branch deployment, and disconnect the branch by hand after its pull request merges. Correct answer Your answerTurn on pull request previews for main, so that Amplify builds each pull request to its own preview URL and deletes it once the request closes. Correct answer Your answerCreate a separate Amplify app for each developer that connects to the same repository, and have each developer push feature work to that app's branch. Correct answer Your answerAdd an AWS CodeBuild project that builds each pull request and copies the output to its own S3 prefix behind an Amazon CloudFront distribution. Correct answer Your answerExplanation
Amplify Hosting web previews deploy every pull request made against an enabled branch to a unique preview URL, separate from the production URL, and delete that preview, along with any temporary backend environment created for it, when the pull request is closed; each open pull request counts toward the app's branch quota, which closing it releases. Connecting branches manually does give each one a site, but someone has to add and remove every branch, which is exactly the upkeep and the stale sites the reviewers want to avoid. A separate app per developer multiplies build settings, environment variables and domains, and still gives no per-pull-request environment. A custom CodeBuild and CloudFront pipeline reimplements previews by hand and needs its own trigger, routing and cleanup logic.
-
Question 52
Correct IncorrectWhich change supports the new access pattern efficiently without recreating the table?
Add a local secondary index with assigneeId as its partition key and updatedAt as its sort key by calling UpdateTable on Tickets. Correct answer Your answerAdd a global secondary index with assigneeId as its partition key and updatedAt as its sort key by calling UpdateTable. Correct answer Your answerKeep the Scan but run it as a parallel scan with eight segments and a FilterExpression on assigneeId. Correct answer Your answerKeep the Scan but add a ProjectionExpression so that it reads only the assigneeId and updatedAt attributes. Correct answer Your answerExplanation
A global secondary index can be added to an existing table at any time; DynamoDB backfills it from the current items, and the dashboard can then Query by assigneeId with ScanIndexForward set to false to return the newest tickets first. A local secondary index must share the table's partition key, so it could not be keyed on assigneeId, and local secondary indexes can only be defined when the table is created. A parallel scan finishes sooner but still reads all 60 million items and consumes even more read capacity per second. A ProjectionExpression trims what is returned, not what is read, because read capacity is charged on the full size of every item scanned before any projection or filter is applied.
-
Question 53
Correct IncorrectWhich approach adds current org_id and plan claims to the access tokens with the least custom code?
Add a post authentication trigger that reads OrgAccounts and writes org_id and plan into custom user attributes, so that they appear in the tokens after every sign-in. Correct answer Your answerAdd a pre token generation trigger that uses the V1_0 event, reads OrgAccounts, and returns org_id and plan in claimsToAddOrOverride for the access token. Correct answer Your answerAdd a pre token generation trigger that uses the V2_0 event, reads OrgAccounts, and returns org_id and plan as claims under accessTokenGeneration in its response. Correct answer Your answerCreate a user pool group for every organization and every plan, keep memberships in sync with billing, and have the API read both values from cognito:groups. Correct answer Your answerExplanation
The pre token generation trigger runs each time Cognito issues tokens, including on refresh, and the V2_0 event (available on the Essentials and Plus plans) lets the function add claims to the access token through accessTokenGeneration.claimsToAddOrOverride, so a single DynamoDB read at issuance puts current org_id and plan values where the API can authorize on them. A V1_0 event customizes only the ID token, apart from group overrides, so its claimsToAddOrOverride never reaches the access token the API validates. Custom user attributes written by a post authentication trigger appear in the ID token, not the access token, and copying billing data into the directory on every sign-in adds writes and staleness. Encoding organizations and plans as groups means thousands of groups and a sync job for every membership and plan change.
-
Question 54
Correct IncorrectWhich change detects conflicting writes so they can be retried, while keeping the read-modify-write logic in code?
Set ConsistentRead to true on every GetItem call so that each task always reads the most recently written version of the item. Correct answer Your answerRead the item with TransactGetItems and then write it with TransactWriteItems so that the two steps run inside a transaction. Correct answer Your answerEnable DynamoDB Streams on the table and have an AWS Lambda function reconcile conflicting versions after they are written. Correct answer Your answerAdd a version attribute and make each PutItem conditional on it matching the value read, incrementing it in the same write. Correct answer Your answerExplanation
Optimistic locking makes each write conditional on the item being unchanged since it was read: the PutItem carries a ConditionExpression that the version attribute still equals the value read and sets it one higher, so a concurrent writer gets a ConditionalCheckFailedException, rereads the item and reapplies its rules instead of overwriting. Strongly consistent reads return the latest committed item at read time, but another task can still write between that read and the PutItem. TransactGetItems and TransactWriteItems are separate calls, and no transaction spans them; an unconditional write inside TransactWriteItems overwrites just as PutItem does. A stream-driven reconciler repairs drift only after the lost update has happened, other tasks read the wrong count in the meantime, and it would have to re-derive the business rules from old and new images.
-
Question 55
Correct IncorrectWhich change guarantees that production runs the exact image that passed the integration tests?
Add an ECR lifecycle policy that expires untagged images after one day so that only the most recent release-candidate image remains in the repository. Correct answer Your answerConfigure ECR replication to a second repository that only production uses, so that production deployments pull from a copy of the tested image. Correct answer Your answerEnable tag immutability, tag each build with its commit ID, and pass the image digest from the build to the test and production task definitions. Correct answer Your answerSet force new deployment on the production ECS service so that its tasks always pull the newest release-candidate image when the deployment stage runs. Correct answer Your answerExplanation
A digest is a content hash that identifies one image and can never point at anything else, and tag immutability stops a later push from overwriting an existing tag, so tagging by commit ID and passing the digest through the pipeline makes the test stage and the production stage reference the same bytes. An untagged-image lifecycle policy only cleans up old images; it does nothing to stop release-candidate being moved to a new image. Replication copies whatever is pushed, including the overwriting push, so the production repository would receive the untested image as well. Forcing a new deployment makes tasks pull the current target of the mutable tag, which is exactly the behavior that caused the incident.
-
Question 56
Correct IncorrectWhich configuration meets both requirements?
Use alias/claims-env for encryption at rest, encrypt the token with the encryption helpers and that key, decrypt it with KMS during init, and grant the role kms:Decrypt. Correct answer Your answerUse alias/claims-env for encryption at rest, and grant the execution role kms:Decrypt so that Lambda decrypts PARTNER_API_TOKEN before the handler starts. Correct answer Your answerKeep the default AWS managed key for encryption at rest, and enable the encryption helpers so that the console encrypts the token in transit with alias/claims-env. Correct answer Your answerUse alias/claims-env for encryption at rest, encrypt the token with the encryption helpers, and rely on Lambda to decrypt the value before the handler starts. Correct answer Your answerExplanation
Two separate settings are needed: choosing alias/claims-env as the at-rest key replaces the AWS managed key, and the encryption helpers encrypt the token client-side with that key, so the stored and returned value is ciphertext that the function decrypts itself with a KMS Decrypt call, cached once during initialization, which needs kms:Decrypt on the execution role. Selecting the customer managed key for encryption at rest alone satisfies the first requirement only, because Lambda decrypts at-rest values transparently and the configuration shows plaintext to anyone allowed to use the key. Keeping the AWS managed key fails the at-rest requirement outright. Lambda never decrypts helper-encrypted values on the function's behalf, so without decryption code the handler receives a base64 ciphertext string.
-
Question 57
Correct IncorrectWhich change lets new tasks finish starting while still replacing tasks that become unhealthy after startup?
Turn on the deployment circuit breaker with rollback so that the service returns to the last working task definition automatically. Correct answer Your answerRaise the minimum healthy percent of the service to 100 so that ECS keeps the old tasks running until the new tasks pass checks. Correct answer Your answerSet a health check grace period of 180 seconds on the ECS service and tune the target group health check interval and threshold. Correct answer Your answerChange the target group health check success codes to 200-499 so that a task that is still starting passes the health check. Correct answer Your answerExplanation
The service health check grace period tells the ECS scheduler to ignore load balancer health check results for that many seconds after a task starts, so 180 seconds covers the 150-second warm-up, and tuning the target group interval and unhealthy threshold keeps detection prompt but tolerant once the grace period ends, so tasks that fail later are still replaced. The circuit breaker would detect the repeated failures and roll back to the old revision, so the new version would never deploy. A minimum healthy percent of 100 keeps capacity up during the rollout, but the new tasks are still killed at 30 seconds and the deployment still never completes. Accepting 200-499 does not help a task that is not yet listening, and it would permanently hide real errors.
-
Question 58
Correct IncorrectWhich change removes expired sessions at the lowest cost?
Enable Time to Live on the table with expiresAt as the TTL attribute so expired items are deleted in the background. Correct answer Your answerAdd a global secondary index keyed on expiresAt and change the nightly function to Query it before deleting the items. Correct answer Your answerWrite sessions into a new table every day and have a scheduled function delete the table that is more than a day old. Correct answer Your answerEnable DynamoDB Streams on the table with a retention period that matches the session lifetime so old items age out. Correct answer Your answerExplanation
DynamoDB Time to Live deletes items whose TTL attribute, a Number holding an epoch time in seconds, is in the past, and those background deletions consume no write capacity, so the nightly scan and its delete charges disappear. Deletion is not instant (it typically happens within a few days of expiry), so the application should keep ignoring sessions whose expiresAt has passed. A GSI on expiresAt makes finding expired items cheaper, but every delete is still a paid write and the index adds its own write cost. Rolling daily tables avoid per-item deletes but break sessions that span midnight and add table-management code. DynamoDB Streams keeps change records for a fixed 24 hours; it has no configurable retention and no effect on the items in the table.
-
Question 59
Correct IncorrectWhich approach gives the mobile team a working endpoint that returns the agreed responses without writing or running any backend code?
Create placeholder Lambda functions that return hardcoded JSON for each route and attach them to the methods with Lambda proxy integration. Correct answer Your answerConfigure each method with a mock integration whose integration responses return the agreed JSON bodies and status codes through mapping templates. Correct answer Your answerEnable API caching on the stage with a long time to live and prime the cache with sample responses so that requests never reach a backend. Correct answer Your answerHave each mobile developer run sam local start-api against a template that declares the routes so that the endpoints respond on each laptop. Correct answer Your answerExplanation
A mock integration makes API Gateway answer the request itself: the integration request mapping template selects a status code, and the integration responses return the agreed body and headers through mapping templates, so the deployed stage serves the contract over HTTPS with no backend at all and can later be switched to the real Lambda integrations. Placeholder Lambda functions work, but they are backend code that someone has to write, deploy and pay for, which the requirement rules out. API caching stores responses that a backend has already produced and cannot be primed with sample data, so every request would still need an integration. The sam local start-api command runs function code from the template locally, so with no functions written there is nothing to serve, and it would not be a shared endpoint anyway.
-
Question 60
Correct IncorrectWhich approach meets these requirements with the least operational overhead?
Add a subscription filter that streams the log group to a Lambda function, which redacts the values and writes the clean events to a second log group for the support team. Correct answer Your answerCreate a data protection policy on the log group with managed data identifiers for email addresses and credit card numbers, and grant logs:Unmask only to security. Correct answer Your answerEnable Amazon Macie automated sensitive data discovery for the account, so that it detects and masks the values in the log group as new log events arrive. Correct answer Your answerCreate metric filters that match email address and card number patterns in the log group, and alarm the security team whenever either filter matches an event. Correct answer Your answerExplanation
A CloudWatch Logs data protection policy detects the selected managed data identifiers as events are ingested and masks them at every egress point, including Logs Insights, metric filters and subscription filters, while principals granted logs:Unmask can still see the original values; it needs no code change. It applies only to events ingested after the policy is created, so older events stay as they were. A redaction pipeline built on a subscription filter is custom code to run and pay for, and the original log group still holds the unmasked values that support can query. Amazon Macie analyzes objects in Amazon S3, not CloudWatch Logs log groups, and it reports findings rather than masking data. Metric filters only count matches; every value stays fully visible.
-
Question 61
Correct IncorrectWhich approach meets the requirement with the least operational overhead?
Enable a DynamoDB stream on Pledges with the NEW_IMAGE view and add a Lambda trigger that adds each pledge to its campaign total. Correct answer Your answerEnable Kinesis Data Streams for DynamoDB on Pledges and have an Amazon Data Firehose stream deliver the records into CampaignTotals. Correct answer Your answerEnable CloudWatch Contributor Insights for DynamoDB on Pledges and read the per-campaign figures from its contributor reports. Correct answer Your answerRun the existing scan function every minute from an Amazon EventBridge Scheduler schedule and keep rewriting every total. Correct answer Your answerExplanation
DynamoDB Streams captures every item change, and a Lambda event source mapping on the stream invokes the function within seconds, so it can apply an UpdateItem with an ADD expression to the matching campaign's total for each INSERT record. Stream records can be processed more than once after a retry, so the function should guard against double counting, for example with a conditional write keyed on the pledge ID. Amazon Data Firehose has no DynamoDB destination, so it cannot write into CampaignTotals. Contributor Insights reports the most frequently accessed and throttled keys, not sums of attribute values. Scanning every minute still lags by up to a minute and multiplies the already growing scan cost by fifteen.
-
Question 62
Correct IncorrectWhere should the developer look to find the root cause of the failed update?
The status reason of the UPDATE_ROLLBACK_COMPLETE event, which is the newest entry at the top of the stack events list. Correct answer Your answerThe results of a drift detection run on the stack, which list each resource whose live configuration differs from the template. Correct answer Your answerThe status reason of the earliest CREATE_FAILED or UPDATE_FAILED event that was recorded after the update operation began. Correct answer Your answerThe status reason of the most recent UPDATE_FAILED event whose reason reads Resource update cancelled in the stack events. Correct answer Your answerExplanation
When one resource fails, CloudFormation cancels the operations still in flight and rolls back, so the cause is recorded on the first failure event of the update, and reading the stack events in time order to the earliest CREATE_FAILED or UPDATE_FAILED entry shows the real error, such as a permissions denial or an invalid property, in its status reason. The UPDATE_ROLLBACK_COMPLETE event only reports that the rollback finished. Drift detection compares live resource configuration with the template; after a successful rollback the resources match the previous template, and drift says nothing about why the update failed. Events reading Resource update cancelled are consequences of the first failure, since CloudFormation stopped those updates because something else had already failed.
-
Question 63
Correct IncorrectWhich approach meets these requirements with the least custom tooling?
Save the payloads as shareable test events with sam remote test-event put, and have each developer run sam remote invoke with the --test-event-name option. Correct answer Your answerSave each payload as a private test event in the Lambda console under a common naming scheme, and have the developers invoke the function from the console. Correct answer Your answerKeep the payloads in the repository's events folder and have each developer run sam local invoke with the -e option against the function on a laptop. Correct answer Your answerCommit the payloads to the repository and have each developer pass the chosen file to aws lambda invoke with the --payload option against the function. Correct answer Your answerExplanation
Shareable test events are stored in the Amazon EventBridge schema registry and are visible to everyone in the account who has the schema permissions, so the same named events appear in the Lambda console's test tab, and the SAM CLI manages them with sam remote test-event and sends one to the deployed function with sam remote invoke and --test-event-name. Private test events in the console are visible only to the user who created them, so a shared naming scheme does not share them. Running sam local invoke tests a local container rather than the deployed function, with its real role, configuration and downstream resources. Committing files and calling aws lambda invoke does reach the deployed function, but the events live outside the account and never appear in the console's test tab.
-
Question 64
Correct IncorrectWhich approach meets the requirement with the least development and maintenance effort?
Turn on DynamoDB encryption at rest with a customer managed KMS key for SupportNotes, so that the note text is protected before it is stored in the table. Correct answer Your answerEnable Amazon Macie for the account, so that it scans the SupportNotes table on a schedule and masks the personal data in each item after it is written. Correct answer Your answerMaintain regular expressions for names, phone numbers, email addresses and street addresses, and apply them in notes-writer to each note before the write. Correct answer Your answerCall Amazon Comprehend DetectPiiEntities from notes-writer, replace each returned offset range with its entity type, and then write the redacted text. Correct answer Your answerExplanation
DetectPiiEntities is a synchronous API that accepts up to 100 KB of English or Spanish text and returns each PII entity's type, confidence score and begin and end offsets, so notes-writer can swap each span for a label such as [PHONE] and store only redacted text, with the model maintained by AWS. ContainsPiiEntities returns only the entity labels present, which suits a fast yes-or-no check but not span replacement. Encryption at rest with a customer managed key protects the stored bytes, yet every reader with table access still sees the names and numbers in plaintext. Amazon Macie discovers sensitive data in Amazon S3, not in DynamoDB items, and reports findings rather than masking anything. Hand-written regular expressions can catch email addresses but are poor at names and street addresses, and they become a pattern list the team must maintain forever.
-
Question 65
Correct IncorrectWhich approach provides this search capability while keeping DynamoDB as the system of record?
Add a global secondary index with title as its sort key and query it with a begins_with condition on the search text. Correct answer Your answerPut a DynamoDB Accelerator (DAX) cluster in front of the table so that the repeated Scan requests are cached. Correct answer Your answerRun PartiQL SELECT statements with a WHERE clause that uses contains() instead of calling the Scan API directly. Correct answer Your answerReplicate the table into Amazon OpenSearch Service, for example with the zero-ETL integration, and query its index. Correct answer Your answerExplanation
Amazon OpenSearch Service builds an inverted index with text analyzers, fuzzy matching, relevance scoring and aggregations for facets, which is what full-text search needs, and the DynamoDB zero-ETL integration, built on OpenSearch Ingestion, keeps the index in sync with the table without custom pipeline code while orders and inventory stay in DynamoDB. A begins_with key condition matches only a case-sensitive prefix of one sort key attribute, with no typo tolerance or ranking. DAX caches identical requests, but each distinct search is a new Scan, and a cached scan still has no relevance ranking or fuzzy matching. A PartiQL SELECT whose WHERE clause has no key condition is executed as a full table scan, so it costs the same as the Scan it replaces.