☰ All modules Tier 3 · Monitoring (CloudWatch, X-Ray, CloudTrail, EventBridge) GuideCheat sheet ‹ other-servicescontainers ›
Contents
  1. How Monitoring (CloudWatch, X-Ray, CloudTrail, EventBridge) appears on DVA-C02
  2. 1. CloudWatch metrics and custom metrics
  3. 2. Metrics from logs with EMF and metric filters
  4. 3. CloudWatch Logs ingestion retention and the agent
  5. 4. Logs Insights subscriptions and S3 export
  6. 5. CloudWatch alarms and Synthetics canaries
  7. 6. EventBridge rules event patterns and targets
  8. 7. EventBridge schema registry and cross account events
  9. 8. Distributed tracing concepts and instrumentation
  10. 9. Trace sampling rules APIs and troubleshooting
  11. 10. CloudTrail auditing and choosing the right tool
  12. Quick decision rules
  13. Changed vs older material

Monitoring (CloudWatch, X-Ray, CloudTrail, EventBridge) — DVA-C02 Mastery Guide

  • Sources: notes/source/13.Monitoring.pdf (course chapter 13: monitoring, troubleshooting and audit with CloudWatch, X-Ray, CloudTrail and EventBridge). The course serves as the syllabus only; all wording here is original.
  • Written 2026-10-12; values checked against AWS docs on 2026-10-12. The marker ⚠️ Changed: <current>. Older material may say <old>. flags a value or behaviour that differs from the course or from older practice tests: learn the current value. ⚠️ unverified marks a claim that could not be confirmed in current AWS documentation: don't rely on it. Every change is listed in Changed vs older material and, once confirmed, in notes/current-facts.md.
  • Tier 3 (supporting), bank target 30 questions. Domain: Troubleshooting and Optimization (config key troubleshooting).
  • How to use it: /explain <topic> teaches from these sections (concept → exam facts → developer angle → traps → 3 check questions); /quiz monitoring asks bank questions whose source_note links point at the ## N. headings below; /drill monitoring fires short recall prompts from notes/monitoring-cheat-sheet.md. Suggested loop: read a section, answer its two practice questions before opening the answers, /explain what is still unclear, then /quiz and /drill.

How Monitoring (CloudWatch, X-Ray, CloudTrail, EventBridge) appears on DVA-C02

Domain 4 (Troubleshooting and Optimization, 18 % of the scored exam) is where this module lives. Its task statements ask you to find root causes from metrics, logs and traces, to instrument code so it can be observed, and to tune a workload with what you measured. EventBridge also shows up in Domain 1 questions about event-driven integration, and CloudTrail in Domain 2 questions about auditing.

What the exam expects from a developer:

Typical question shapes: a scenario with one deciding constraint (least operational overhead, no code changes, near real time, least privilege, longest retention at lowest cost); a missing-data or missing-trace troubleshooting case; "Which TWO steps…" with five options; the exact API action, CLI command, IAM permission or setting that does the job.

Out of scope: OS-level agent administration and network design. EC2-specific metrics, detailed monitoring, status checks and instance recovery are owned by the EC2 module (see notes/ec2-mastery-guide.md#11-cloudwatch-for-ec2-metrics-agent-and-status-checks). Lambda logging controls and active tracing: notes/lambda-guide.md#12-observability-with-logs-metrics-and-traces. API Gateway execution and access logs: notes/api-gateway-guide.md#12-logging-metrics-and-tracing. KMS encryption of log groups: notes/security-encryption-guide.md#12-cloudwatch-logs-encryption-and-codebuild-secrets. Firehose and Kinesis Data Streams themselves: notes/sqs-sns-kinesis-guide.md. ECS log drivers (awslogs, FireLens): notes/containers-guide.md#2-task-definitions-and-container-settings. Quota-usage alarms (AWS/Usage, SERVICE_QUOTA()): notes/cli-sdk-policies-guide.md#8-service-quotas-and-api-rate-limits. Pipeline and deployment notifications: notes/cicd-guide.md#12-manual-approvals-and-pipeline-monitoring.

⚠️ Changed: CloudWatch Evidently was discontinued on 2025-10-17 (full shutdown); feature flags and launches now use AWS AppConfig feature flags, and A/B or multivariate experiments use AWS AppConfig experimentation (generally available since 2026-07-01, results analysed in CloudWatch or your own tools). Older material may say CloudWatch Evidently is the service for feature flags and A/B tests. AppConfig itself: notes/other-services-guide.md#10-appconfig-feature-flags-validators-and-deployment-strategies.

# Topic Why it is on the exam
1 CloudWatch metrics and custom metrics Namespaces, dimensions, resolution and retention decide whether your numbers can be graphed, aggregated and alarmed on
2 Metrics from logs with EMF and metric filters The two ways to turn log lines into metrics without extra API calls, and their limits
3 CloudWatch Logs ingestion retention and the agent Log groups, streams, retention, log classes, size limits, masking and getting logs off a server
4 Logs Insights subscriptions and S3 export Ad hoc queries vs near-real-time streaming vs batch export, including cross-account delivery
5 CloudWatch alarms and Synthetics canaries Alarm evaluation, missing data, actions, composite alarms, and probing endpoints with canaries
6 EventBridge rules event patterns and targets Event-driven integration: patterns, targets, permissions, retries, schedules, archive and replay
7 EventBridge schema registry and cross account events Typed events from schemas, bus resource policies, multi-account aggregation and the new bus type
8 Distributed tracing concepts and instrumentation X-Ray segments, annotations vs metadata, SDK/daemon vs OpenTelemetry, IAM and service integrations
9 Trace sampling rules APIs and troubleshooting Controlling trace volume without redeploying, reading traces by API, and "why are there no traces?"
10 CloudTrail auditing and choosing the right tool Management, data and Insights events, retention, reacting to API calls, CloudWatch vs X-Ray vs CloudTrail

1. CloudWatch metrics and custom metrics

Concept

Exam facts

Developer angle

Publish a high-resolution metric, a batch of raw values, and a statistic set (the credentials come from the instance or task role):

aws cloudwatch put-metric-data --namespace OrdersApp --metric-name CheckoutLatency \
  --dimensions Service=checkout,Env=prod --unit Milliseconds --value 182 --storage-resolution 1

aws cloudwatch put-metric-data --namespace OrdersApp --metric-name CheckoutLatency \
  --dimensions Service=checkout,Env=prod --unit Milliseconds \
  --statistic-values Sum=1460,Minimum=95,Maximum=410,SampleCount=8

aws cloudwatch list-metrics --namespace OrdersApp --metric-name CheckoutLatency
import boto3

cloudwatch = boto3.client("cloudwatch")
cloudwatch.put_metric_data(
    Namespace="OrdersApp",
    MetricData=[{
        "MetricName": "CheckoutLatency",
        "Dimensions": [{"Name": "Service", "Value": "checkout"}],
        "Unit": "Milliseconds",
        "Values": [95.0, 120.0, 410.0],   # raw values: percentiles stay available
        "Counts": [3.0, 4.0, 1.0],        # how often each value occurred
        "StorageResolution": 60,
    }],
)

Read an error rate with metric math in one call (queries.json):

[
  {"Id": "errors", "ReturnData": false,
   "MetricStat": {"Metric": {"Namespace": "AWS/Lambda", "MetricName": "Errors",
                             "Dimensions": [{"Name": "FunctionName", "Value": "checkout"}]},
                  "Period": 60, "Stat": "Sum"}},
  {"Id": "calls", "ReturnData": false,
   "MetricStat": {"Metric": {"Namespace": "AWS/Lambda", "MetricName": "Invocations",
                             "Dimensions": [{"Name": "FunctionName", "Value": "checkout"}]},
                  "Period": 60, "Stat": "Sum"}},
  {"Id": "errorRate", "Expression": "100 * errors / calls", "Label": "Error rate %"}
]
aws cloudwatch get-metric-data --metric-data-queries file://queries.json \
  --start-time 2026-10-12T08:00:00Z --end-time 2026-10-12T09:00:00Z

Traps

Practice questions

  1. Forty containers report payment latency for the same service. The team wants a single CloudWatch metric that shows p99 latency across all containers, while keeping the number of PutMetricData calls low. What should the developer do?

    • A. Call PutMetricData once per request and add a ContainerId dimension to every data point.
    • B. Aggregate in each container and publish a statistic set with Sum, Minimum, Maximum and SampleCount every minute.
    • C. Buffer raw latencies in each container and publish them with the Values and Counts arrays under one shared dimension set every minute.
    • D. Publish the per-container average every minute as a single Value.
  2. A nightly job back-fills order totals into a custom metric with PutMetricData, using timestamps from the last 30 days. Some calls fail, and the newly created metric doesn't appear in aws cloudwatch list-metrics right after the job starts. Which TWO statements explain this? (Select TWO.)

    • A. Custom metrics must be published to a namespace that starts with AWS/.
    • B. CloudWatch rejects data points whose timestamps are more than two weeks in the past.
    • C. Each PutMetricData call accepts at most 20 metrics, so the larger batches fail.
    • D. A new metric can take up to 15 minutes to appear in ListMetrics results.
    • E. Metrics published with StorageResolution 60 are visible only after 15 days.
Answers
  1. C. Values/Counts keep raw values (percentiles work) and batch up to 150 values per metric per call; one shared dimension set means one metric for the whole fleet. A multiplies calls and creates 40 metrics that can't be combined into one percentile; B and D lose the raw distribution, so p99 isn't available.
  2. B, D. Timestamps are accepted only from 2 weeks back to 2 hours ahead, and new metrics take up to 15 minutes to be listed. A is wrong (AWS/ is reserved for AWS services); C is an old limit (now 1,000 metrics and 1 MB per call); E is invented.

2. Metrics from logs with EMF and metric filters

Concept

Exam facts

Developer angle

An EMF log line written by a Lambda function (two dimension sets → two metrics per name):

import json
import time

def handler(event, context):
    order = event["order"]
    print(json.dumps({
        "_aws": {
            "Timestamp": int(time.time() * 1000),
            "CloudWatchMetrics": [{
                "Namespace": "OrdersApp",
                "Dimensions": [["Service"], ["Service", "Channel"]],
                "Metrics": [{"Name": "OrderValue", "Unit": "None"},
                            {"Name": "OrdersPlaced", "Unit": "Count"}],
            }],
        },
        "Service": "checkout",
        "Channel": order["channel"],
        "OrderValue": order["total"],
        "OrdersPlaced": 1,
        "orderId": order["id"],          # searchable context, not a dimension
        "requestId": context.aws_request_id,
    }))
    return {"ok": True}

A metric filter on JSON logs, tested before it goes live:

aws logs test-metric-filter --filter-pattern '{ $.level = "ERROR" }' \
  --log-event-messages '{"level":"ERROR","msg":"card declined"}' '{"level":"INFO","msg":"ok"}'

aws logs put-metric-filter --log-group-name /orders/app --filter-name app-errors \
  --filter-pattern '{ $.level = "ERROR" }' \
  --metric-transformations metricName=AppErrors,metricNamespace=OrdersApp,metricValue=1,defaultValue=0

aws logs describe-metric-filters --log-group-name /orders/app

Traps

Practice questions

  1. A Lambda function processes orders. The team needs a metric OrdersPlaced broken down by four attributes (Region, Channel, PaymentType, Tier), and every order's full context must stay searchable in the logs. The function must not make extra synchronous API calls. What should the developer do?

    • A. Call PutMetricData from the handler with the four attributes as dimensions.
    • B. Write each order as an embedded metric format JSON line to standard output with a dimension set containing the four keys.
    • C. Create a metric filter on the function's log group that extracts the four attributes as dimensions.
    • D. Record the four attributes as X-Ray annotations and graph them in CloudWatch.
  2. A developer adds a metric filter for ERROR to the log group /orders/app and creates an alarm on the resulting metric. Which TWO statements are correct? (Select TWO.)

    • A. The filter also counts ERROR events ingested during the week before it was created.
    • B. The filter can't be created if /orders/app uses the Infrequent Access log class.
    • C. Adding requestId as a filter dimension can cause CloudWatch Logs to disable the filter.
    • D. A default value of 0 can be combined with up to three dimensions.
    • E. Metrics created by metric filters are stored at 1-second resolution by default.
Answers
  1. B. EMF publishes the metric asynchronously from the log line, supports dimension sets of up to 30 keys, and keeps the full event searchable. A adds a synchronous call per order; C fails because a metric filter accepts at most 3 dimensions; D creates trace annotations, not metrics.
  2. B, C. Metric filters exist only on Standard-class log groups, and a filter that generates 1,000 distinct dimension name/value pairs can be disabled. A is wrong (filters aren't retroactive); D is wrong (no default value with dimensions); E is invented.

3. CloudWatch Logs ingestion retention and the agent

Concept

Exam facts

Developer angle

aws logs create-log-group --log-group-name /orders/app --log-group-class STANDARD
aws logs put-retention-policy --log-group-name /orders/app --retention-in-days 30
aws logs create-log-stream --log-group-name /orders/app --log-stream-name web-1
aws logs put-log-events --log-group-name /orders/app --log-stream-name web-1 \
  --log-events '[{"timestamp":1760259600000,"message":"{\"level\":\"ERROR\",\"orderId\":\"42\"}"}]'

aws logs tail /orders/app --follow --since 15m --filter-pattern ERROR
aws logs start-live-tail \
  --log-group-identifiers arn:aws:logs:eu-west-1:111122223333:log-group:/orders/app \
  --log-event-filter-pattern ERROR
aws logs delete-retention-policy --log-group-name /orders/app    # back to "never expire"

Writing structured logs from code (the SDK batches nothing for you; prefer a library, the agent or the service integration in production):

import json, time
import boto3

logs = boto3.client("logs")
logs.put_log_events(logGroupName="/orders/app", logStreamName="web-1", logEvents=[{
    "timestamp": int(time.time() * 1000),
    "message": json.dumps({"level": "INFO", "orderId": "42", "latencyMs": 87})}])

Traps

Practice questions

  1. Compliance requires that an application's logs in CloudWatch Logs are kept for 400 days and then deleted automatically. The log group currently uses the default retention. Which solution has the LEAST operational overhead?

    • A. Export the log group to Amazon S3 every day, add an S3 Lifecycle expiration rule, and then delete the log group.
    • B. Schedule a Lambda function that deletes log streams older than 400 days.
    • C. Recreate the log group in the Infrequent Access log class, which expires events after 400 days.
    • D. Run aws logs put-retention-policy --log-group-name /payments/app --retention-in-days 400.
  2. Applications on EC2 instances that require IMDSv2 must send /var/log/app/*.log and memory utilization to CloudWatch. The instances run the older CloudWatch Logs agent, and no logs arrive. Which TWO actions fix the problem? (Select TWO.)

    • A. Replace the CloudWatch Logs agent with the unified CloudWatch agent and configure the log files and memory metrics.
    • B. Enable EC2 detailed monitoring on the instances.
    • C. Change the log group retention to never expire.
    • D. Create a subscription filter on the target log group.
    • E. Attach the CloudWatchAgentServerPolicy managed policy to the instances' IAM role.
Answers
  1. D. 400 days is a valid retention value, and CloudWatch Logs then deletes expired events itself. A and B add moving parts; C is wrong twice: the class can't be changed on an existing group and the class doesn't set retention.
  2. A, E. The deprecated Logs agent doesn't work with IMDSv2-only instances and can't collect memory; the unified agent does, but it needs the instance role permissions in CloudWatchAgentServerPolicy. B only changes EC2's own metric period; C and D don't make logs arrive.

4. Logs Insights subscriptions and S3 export

Concept

Exam facts

Developer angle

Logs Insights QL error trend (JSON fields such as level are discovered automatically):

fields @timestamp, @message, @logStream
| filter level = "ERROR" and service = "checkout"
| stats count(*) as errors by bin(5m)
| sort errors desc
| limit 20

Run it from the CLI (times in epoch seconds), then fetch the results with the returned ID:

QUERY_ID=$(aws logs start-query --log-group-names /orders/app /orders/worker \
  --start-time 1760256000 --end-time 1760259600 \
  --query-string 'fields @timestamp, requestId, latencyMs | sort latencyMs desc | limit 20' \
  --query queryId --output text)
aws logs get-query-results --query-id "$QUERY_ID"

Subscription filters to Lambda (resource-based policy, no role) and to Kinesis (role, random distribution):

aws lambda add-permission --function-name log-processor --statement-id cwlogs-orders \
  --principal logs.amazonaws.com --action lambda:InvokeFunction \
  --source-arn "arn:aws:logs:eu-west-1:111122223333:log-group:/orders/app:*" \
  --source-account 111122223333
aws logs put-subscription-filter --log-group-name /orders/app --filter-name to-lambda \
  --filter-pattern '{ $.level = "ERROR" }' \
  --destination-arn arn:aws:lambda:eu-west-1:111122223333:function:log-processor

aws logs put-subscription-filter --log-group-name /orders/app --filter-name to-stream \
  --filter-pattern "" --distribution Random \
  --destination-arn arn:aws:kinesis:eu-west-1:111122223333:stream/orders-logs \
  --role-arn arn:aws:iam::111122223333:role/CWLtoKinesisRole

Cross-account: the recipient (999999999999) publishes a destination; the sender subscribes to it:

# recipient account
aws logs put-destination --destination-name central-logs \
  --target-arn arn:aws:kinesis:eu-west-1:999999999999:stream/central-logs \
  --role-arn arn:aws:iam::999999999999:role/CWLtoKinesisRole
aws logs put-destination-policy --destination-name central-logs --access-policy file://access.json
# sender account
aws logs put-subscription-filter --log-group-name /orders/app --filter-name to-central \
  --filter-pattern "" \
  --destination-arn arn:aws:logs:eu-west-1:999999999999:destination:central-logs

access.json (allow one sender account to subscribe):

{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"AWS": "111111111111"},
  "Action": "logs:PutSubscriptionFilter", "Resource": "arn:aws:logs:eu-west-1:999999999999:destination:central-logs"}]}

One-off export of a day of logs (epoch milliseconds):

aws logs create-export-task --log-group-name /orders/app \
  --from 1759276800000 --to 1759363200000 \
  --destination orders-log-archive --destination-prefix app/2025-10-01

Traps

Practice questions

  1. A security team needs every log event from a production account's /payments/app log group delivered within minutes to a Kinesis data stream in a separate security account, for intrusion detection. Which configuration meets these requirements?

    • A. Run CreateExportTask every hour to an S3 bucket in the security account and read new objects from there.
    • B. In the security account, create a CloudWatch Logs destination for the stream with an access policy that allows the production account; in the production account, create a subscription filter that targets the destination ARN.
    • C. Schedule a CloudWatch Logs Insights query every minute in the production account and write the results to the stream.
    • D. In the production account, create a subscription filter whose destination ARN is the stream in the security account, using a role in the production account.
  2. A developer must find the 20 slowest requests of the last hour across three log groups from a shell script. Which TWO statements are correct? (Select TWO.)

    • A. A Logs Insights query can run for up to 24 hours before it times out.
    • B. Query results are stored for 90 days after the query completes.
    • C. aws logs start-query returns a queryId, and the rows are retrieved with aws logs get-query-results.
    • D. Logs Insights can query log groups that use the Infrequent Access log class.
    • E. Queries written in OpenSearch SQL are not billed for the data they scan.
Answers
  1. B. Cross-account streaming uses a destination (stream + role) in the recipient account, an access policy that allows the sender, and a subscription filter in the sender account. A is batch (up to 12 hours of delay); C isn't a streaming mechanism; D fails because a subscription filter can't target another account's stream directly.
  2. C, D. StartQuery is asynchronous and GetQueryResults returns the rows; Infrequent Access log groups support most Logs Insights QL commands. A is wrong (60-minute timeout); B is wrong (7 days); E is wrong (billing is per GB scanned for every language).

5. CloudWatch alarms and Synthetics canaries

Concept

Exam facts

Developer angle

A p99 latency alarm (3 of 5 one-minute points), a heartbeat-style alarm, and a composite that ignores deployments:

aws cloudwatch put-metric-alarm --alarm-name checkout-p99-high \
  --namespace OrdersApp --metric-name CheckoutLatency --dimensions Name=Service,Value=checkout \
  --extended-statistic p99 --period 60 --evaluation-periods 5 --datapoints-to-alarm 3 \
  --threshold 800 --comparison-operator GreaterThanThreshold --treat-missing-data notBreaching \
  --alarm-actions arn:aws:sns:eu-west-1:111122223333:ops-alerts

aws cloudwatch put-metric-alarm --alarm-name orders-heartbeat-missing \
  --namespace OrdersApp --metric-name OrdersPlaced --dimensions Name=Service,Value=checkout \
  --statistic Sum --period 300 --evaluation-periods 2 --threshold 1 \
  --comparison-operator LessThanThreshold --treat-missing-data breaching \
  --alarm-actions arn:aws:lambda:eu-west-1:111122223333:function:orders-remediate

aws cloudwatch put-composite-alarm --alarm-name checkout-degraded \
  --alarm-rule 'ALARM("checkout-p99-high") AND ALARM("checkout-5xx-high") AND NOT ALARM("deploy-in-progress")' \
  --alarm-actions arn:aws:sns:eu-west-1:111122223333:pager

Let the alarm invoke the remediation function, then test the whole chain:

aws lambda add-permission --function-name orders-remediate --statement-id cw-alarm \
  --action lambda:InvokeFunction --principal lambda.alarms.cloudwatch.amazonaws.com \
  --source-account 111122223333 \
  --source-arn arn:aws:cloudwatch:eu-west-1:111122223333:alarm:orders-heartbeat-missing

aws cloudwatch set-alarm-state --alarm-name orders-heartbeat-missing \
  --state-value ALARM --state-reason "end-to-end test of the remediation action"
aws cloudwatch describe-alarm-history --alarm-name orders-heartbeat-missing \
  --history-item-type StateUpdate

Create and start a canary whose script is already zipped in S3 (runtime version names change often, so the current one is passed in a variable):

aws synthetics create-canary --name checkout-api \
  --code Handler=index.handler,S3Bucket=canary-code-111122223333,S3Key=checkout-canary.zip \
  --artifact-s3-location s3://canary-artifacts-111122223333/checkout/ \
  --execution-role-arn arn:aws:iam::111122223333:role/CanaryExecutionRole \
  --schedule Expression="rate(5 minutes)" \
  --runtime-version "$SYNTHETICS_RUNTIME"
aws synthetics start-canary --name checkout-api
aws synthetics get-canary-runs --name checkout-api --max-results 5

Traps

Practice questions

  1. An on-call team wants one page only when both the p99 latency alarm and the 5xx error-rate alarm of a service are in ALARM, and no page while the deploy-in-progress alarm is in ALARM. The solution must not need custom code. What should the developer configure?

    • A. A metric math alarm that averages the latency and error-rate metrics against one threshold.
    • B. A Lambda function subscribed to both alarms' SNS topics that checks the third alarm before paging.
    • C. A composite alarm with the rule ALARM("p99-high") AND ALARM("5xx-high") AND NOT ALARM("deploy-in-progress") and an SNS action.
    • D. Higher EvaluationPeriods values on both metric alarms so that they fire less often.
  2. A developer must detect failures of a public checkout API every 5 minutes, even at night when there is no customer traffic, and automatically invoke a remediation Lambda function when failures occur. Which TWO steps meet these requirements? (Select TWO.)

    • A. Enable X-Ray active tracing on the API stage and alarm on the trace count.
    • B. Create a CloudWatch Synthetics canary from the API canary blueprint with a rate(5 minutes) schedule.
    • C. Create a metric filter on the API's access logs that counts 5xx responses.
    • D. Create a composite alarm whose action reboots the API's backend instances.
    • E. Create an alarm on the canary's SuccessPercent metric with the function ARN as the alarm action, and allow lambda.alarms.cloudwatch.amazonaws.com in the function's resource-based policy.
Answers
  1. C. A composite rule expresses AND and NOT across alarm states without code. A can't express "both" and mixes units; B adds custom code; D only delays alarms and still pages on each one separately.
  2. B, E. A canary generates its own requests on a schedule, and an alarm can invoke Lambda directly once the function's resource policy allows the CloudWatch alarms principal. A and C depend on real traffic, which doesn't exist at night; D is wrong because composite alarms can't run EC2 actions and a reboot isn't the requested remediation.

6. EventBridge rules event patterns and targets

Concept

Exam facts

Developer angle

Pattern for custom high-value failures (order-failed-pattern.json):

{
  "source": ["com.example.orders"],
  "detail-type": ["OrderFailed"],
  "detail": {"amount": [{"numeric": [">=", 100]}], "channel": [{"anything-but": "test"}]}
}

Rule on a custom bus, Lambda permission, target with retry policy, DLQ and an input transformer (targets.json below):

aws events create-event-bus --name orders
aws events put-rule --name order-failed --event-bus-name orders \
  --event-pattern file://order-failed-pattern.json --state ENABLED
aws lambda add-permission --function-name order-failed-handler \
  --statement-id eventbridge-order-failed --action lambda:InvokeFunction \
  --principal events.amazonaws.com \
  --source-arn arn:aws:events:eu-west-1:111122223333:rule/orders/order-failed
aws events put-targets --rule order-failed --event-bus-name orders --targets file://targets.json
aws events test-event-pattern --event-pattern file://order-failed-pattern.json --event file://sample-event.json
[
  {
    "Id": "handler",
    "Arn": "arn:aws:lambda:eu-west-1:111122223333:function:order-failed-handler",
    "RetryPolicy": {"MaximumRetryAttempts": 10, "MaximumEventAgeInSeconds": 3600},
    "DeadLetterConfig": {"Arn": "arn:aws:sqs:eu-west-1:111122223333:order-events-dlq"},
    "InputTransformer": {
      "InputPathsMap": {"order": "$.detail.orderId", "amount": "$.detail.amount"},
      "InputTemplate": "{\"orderId\": <order>, \"amount\": <amount>, \"action\": \"refund-check\"}"
    }
  }
]

Publishing from code and resending only the failed entries:

import json
import boto3

events = boto3.client("events")
entries = [{"Source": "com.example.orders", "DetailType": "OrderFailed", "EventBusName": "orders",
            "Detail": json.dumps({"orderId": "42", "amount": 250, "channel": "web"})}]
response = events.put_events(Entries=entries)
if response["FailedEntryCount"]:
    failed = [entry for entry, result in zip(entries, response["Entries"]) if "ErrorCode" in result]
    events.put_events(Entries=failed)  # production code: back off and cap the attempts

A daily job at 02:00 Berlin time with Scheduler, and an archive plus a replay of one bad hour:

aws scheduler create-schedule --name nightly-report \
  --schedule-expression "cron(0 2 * * ? *)" --schedule-expression-timezone "Europe/Berlin" \
  --flexible-time-window Mode=OFF \
  --target '{"Arn":"arn:aws:lambda:eu-west-1:111122223333:function:nightly-report","RoleArn":"arn:aws:iam::111122223333:role/SchedulerInvokeReport"}'

aws events create-archive --archive-name orders-archive --retention-days 30 \
  --event-source-arn arn:aws:events:eu-west-1:111122223333:event-bus/orders
aws events start-replay --replay-name orders-fix-1 \
  --event-source-arn arn:aws:events:eu-west-1:111122223333:archive/orders-archive \
  --event-start-time 2026-10-11T08:00:00Z --event-end-time 2026-10-11T09:00:00Z \
  --destination Arn=arn:aws:events:eu-west-1:111122223333:event-bus/orders

Traps

Practice questions

  1. A Lambda function must run every day at 02:00 Europe/Berlin local time, staying correct across daylight saving changes, with the LEAST operational overhead. What should the developer configure?

    • A. An EventBridge Scheduler schedule with cron(0 2 * * ? *), ScheduleExpressionTimezone set to Europe/Berlin and an execution role that can invoke the function.
    • B. An EventBridge scheduled rule on the default bus with cron(0 2 * * ? *).
    • C. Two EventBridge scheduled rules, one for summer time and one for winter time, enabled and disabled by hand.
    • D. A cron job on an EC2 instance that calls aws lambda invoke at 02:00.
  2. An EventBridge rule on a custom bus targets a Lambda function that a teammate created with the CLI. The rule's MatchedEvents metric rises, but the function is never invoked and FailedInvocations increases. Which TWO actions should the developer take? (Select TWO.)

    • A. Allow events.amazonaws.com to invoke the function in its resource-based policy with the rule ARN as source ARN, or give the target an execution role that allows lambda:InvokeFunction.
    • B. Request a higher quota for the rule's event pattern size.
    • C. Configure a standard SQS queue as the target's dead-letter queue and read the ERROR_CODE and ERROR_MESSAGE attributes of the failed events.
    • D. Move the rule to the default event bus, which doesn't need target permissions.
    • E. Enable an archive on the bus so that failed deliveries are retried automatically.
Answers
  1. A. Scheduler evaluates the cron expression in the given time zone, handles daylight saving, and needs no servers. B runs at 02:00 UTC; C is manual work twice a year; D adds a server to manage.
  2. A, C. The symptom (matched, not invoked) points to missing invoke permission; a DLQ captures undelivered events with the error code that proves it. B and D change nothing about permissions; E stores events for manual replay but doesn't retry deliveries.

7. EventBridge schema registry and cross account events

Concept

Exam facts

Developer angle

Discover schemas on a bus and download Java bindings for one of them:

aws schemas create-discoverer \
  --source-arn arn:aws:events:eu-west-1:111122223333:event-bus/orders
aws schemas list-schemas --registry-name discovered-schemas
aws schemas put-code-binding --registry-name discovered-schemas \
  --schema-name "com.example.orders@OrderFailed" --language Java8
aws schemas get-code-binding-source --registry-name discovered-schemas \
  --schema-name "com.example.orders@OrderFailed" --language Java8 order-failed-bindings.zip

Central bus in account 999999999999 that accepts events from every account of the organization (bus-policy.json):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AllowOrgAccountsToPutEvents",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "events:PutEvents",
    "Resource": "arn:aws:events:eu-west-1:999999999999:event-bus/central-bus",
    "Condition": {"StringEquals": {"aws:PrincipalOrgID": "o-a1b2c3d4e5"}}
  }]
}
# receiving account
aws events create-event-bus --name central-bus
aws events put-permission --event-bus-name central-bus --policy file://bus-policy.json
aws events describe-event-bus --name central-bus

# each sending account: forward EC2 state changes; the role allows events:PutEvents on central-bus
aws events put-rule --name forward-ec2-state \
  --event-pattern '{"source":["aws.ec2"],"detail-type":["EC2 Instance State-change Notification"]}'
aws events put-targets --rule forward-ec2-state --targets \
  '[{"Id":"central","Arn":"arn:aws:events:eu-west-1:999999999999:event-bus/central-bus","RoleArn":"arn:aws:iam::111122223333:role/EventBridgeToCentralBus"}]'

Traps

Practice questions

  1. A company runs workloads in 40 accounts of one AWS Organization. A central operations account must receive every EC2 instance state-change event in its own event bus, with the LEAST operational overhead and least privilege. What should the developer do?

    • A. Attach a resource-based policy to the central bus that allows events:PutEvents from principal * with no condition, and create the forwarding rules in each account.
    • B. Create an IAM user with access keys in the central account and run a polling script in every account that calls PutEvents with those keys.
    • C. Create an organization trail in CloudTrail and query the EC2 events from S3 with Athena every five minutes.
    • D. Attach a resource-based policy to the central bus that allows events:PutEvents from principal * with an aws:PrincipalOrgID condition, and in each account create a rule that targets the central bus with an IAM role allowed to put events on it.
  2. A developer wants strongly typed Java classes for the events that several teams already publish on a custom bus, without writing the schemas by hand. Which TWO steps accomplish this? (Select TWO.)

    • A. Create an archive on the bus with indefinite retention.
    • B. Add an input transformer to every rule so that events have the same shape.
    • C. Register the event formats in the AWS Glue Schema Registry and import them into the bus.
    • D. Start schema discovery on the bus with aws schemas create-discoverer.
    • E. Download code bindings for the discovered schema with the Java8 language.
Answers
  1. D. The organization condition limits senders to your accounts, and a role on each forwarding rule is required for cross-account bus targets. A lets any AWS account publish to the bus; B uses long-term keys and custom polling; C is batch analysis, not event routing.
  2. D, E. Discovery infers and versions the schemas from live events; code bindings turn a schema into Java classes. A stores events but creates no schemas; B changes payloads but discovery still sees the original events; C is a different registry that EventBridge rule-based buses don't use for code bindings.

8. Distributed tracing concepts and instrumentation

Concept

Exam facts

Developer angle

X-Ray SDK for Python (maintenance mode, still common in existing code): patch AWS SDK and HTTP clients, add a subsegment, an annotation and metadata:

from aws_xray_sdk.core import patch_all, xray_recorder

patch_all()  # instruments boto3, requests and other supported libraries

@xray_recorder.capture("price_order")
def price_order(order):
    xray_recorder.put_annotation("customer_tier", order["tier"])   # indexed: searchable
    xray_recorder.put_metadata("order", order, "checkout")         # not indexed: debug detail
    return sum(item["price"] for item in order["items"])

The same with the OpenTelemetry API (ADOT or upstream SDK configured to export to X-Ray):

from opentelemetry import trace

tracer = trace.get_tracer("checkout")

def price_order(order):
    with tracer.start_as_current_span("price_order") as span:
        span.set_attribute("customer_tier", order["tier"])  # metadata in X-Ray unless listed in aws.xray.annotations
        return sum(item["price"] for item in order["items"])

Turn tracing on where AWS runs the collector, and choose the encryption key:

aws lambda update-function-configuration --function-name checkout --tracing-config Mode=Active
aws apigateway update-stage --rest-api-id a1b2c3d4e5 --stage-name prod \
  --patch-operations op=replace,path=/tracingEnabled,value=true
aws xray put-encryption-config --type KMS --key-id alias/xray-traces

.ebextensions/xray-daemon.config for Elastic Beanstalk:

option_settings:
  aws:elasticbeanstalk:xray:
    XRayEnabled: true

ECS task definition (bridge mode) with the daemon as a sidecar container:

{
  "family": "checkout",
  "taskRoleArn": "arn:aws:iam::111122223333:role/CheckoutTaskRole",
  "containerDefinitions": [
    {"name": "xray-daemon", "image": "public.ecr.aws/xray/aws-xray-daemon:3.x", "essential": true,
     "portMappings": [{"containerPort": 2000, "protocol": "udp"}]},
    {"name": "app", "image": "111122223333.dkr.ecr.eu-west-1.amazonaws.com/checkout:1.4.2", "essential": true,
     "links": ["xray-daemon"],
     "environment": [{"name": "AWS_XRAY_DAEMON_ADDRESS", "value": "xray-daemon:2000"}]}
  ]
}

Traps

Practice questions

  1. Developers must find all traces for a given customer_id with a filter expression, and they also want the full order payload available in each trace for debugging. How should the application record these values?

    • A. Record both customer_id and the order payload as metadata.
    • B. Record customer_id as an annotation and the order payload as metadata.
    • C. Record both customer_id and the order payload as annotations.
    • D. Use customer_id as the name of a custom subsegment and log the payload to CloudWatch Logs.
  2. A Java service on EC2 uses the X-Ray SDK for instrumentation, but no traces appear in X-Ray. The instance profile has only an S3 read policy. Which TWO actions address the most likely causes? (Select TWO.)

    • A. Enable active tracing in the Lambda console for the service.
    • B. Make sure a collector (the X-Ray daemon or the CloudWatch agent with trace collection) runs on the instance and listens on UDP port 2000.
    • C. Add the AWSXRayDaemonWriteAccess managed policy to the instance profile's role.
    • D. Allow inbound UDP 2000 from 0.0.0.0/0 in the instance's security group.
    • E. Create a subscription filter on the application's log group that targets X-Ray.
Answers
  1. B. Annotations are indexed (string, number, Boolean) and usable in filter expressions; metadata holds any JSON-serializable value without indexing. A can't be searched; C fails because objects aren't valid annotation values (and annotations are limited to 50 per trace); D doesn't make the ID searchable.
  2. B, C. The SDK only hands segments to a local collector over UDP, and the collector needs xray:PutTraceSegments and xray:PutTelemetryRecords through the instance role. A applies to Lambda; D opens a port that isn't needed (the collector is local and calls the API outbound); E isn't a tracing mechanism.

9. Trace sampling rules APIs and troubleshooting

Concept

Exam facts

Developer angle

A temporary debugging rule that records every POST /checkout* call, without touching the code (debug-rule.json):

{
  "SamplingRule": {
    "RuleName": "debug-checkout-post",
    "Priority": 1,
    "ReservoirSize": 1,
    "FixedRate": 1.0,
    "ServiceName": "checkout",
    "ServiceType": "*",
    "Host": "*",
    "HTTPMethod": "POST",
    "URLPath": "/checkout*",
    "ResourceARN": "*",
    "Version": 1
  }
}
aws xray create-sampling-rule --cli-input-json file://debug-rule.json
aws xray get-sampling-rules --query 'SamplingRuleRecords[].SamplingRule.[RuleName,Priority,FixedRate,ReservoirSize]'
aws xray delete-sampling-rule --rule-name debug-checkout-post     # when the incident is over

Find failed gold-customer traces from the last hour, then fetch their segments:

aws xray get-trace-summaries --start-time 2026-10-12T08:00:00Z --end-time 2026-10-12T09:00:00Z \
  --filter-expression 'annotation[customer_tier] = "gold" AND fault' \
  --query 'TraceSummaries[].Id' --output text
aws xray batch-get-traces --trace-ids 1-5759e988-bd862e3fe1be46a994272793
aws xray get-service-graph --start-time 2026-10-12T08:00:00Z --end-time 2026-10-12T09:00:00Z
aws xray create-group --group-name gold-faults --filter-expression 'annotation[customer_tier] = "gold" AND fault'
from datetime import datetime, timedelta, timezone

import boto3

xray = boto3.client("xray")
end = datetime.now(timezone.utc)
ids = []
for page in xray.get_paginator("get_trace_summaries").paginate(
        StartTime=end - timedelta(hours=1), EndTime=end,
        FilterExpression='annotation[order_status] = "failed"'):
    ids.extend(summary["Id"] for summary in page["TraceSummaries"])

for start in range(0, len(ids), 5):                     # BatchGetTraces takes 5 IDs per call
    for trace in xray.batch_get_traces(TraceIds=ids[start:start + 5])["Traces"]:
        print(trace["Id"], len(trace["Segments"]), "segments")

Traps

Practice questions

  1. During an incident, a team wants X-Ray to record every POST /checkout request handled by a fleet of 30 EC2 instances for the next hour, while all other requests keep the default sampling. The instances use the X-Ray SDK with centralized sampling. What should the developer do?

    • A. Change the local sampling rules file on every instance to a fixed rate of 100 % and redeploy the application.
    • B. Raise the default rule's reservoir to 1,000 requests per second.
    • C. Create a sampling rule with priority 1, reservoir 1, fixed rate 100 %, HTTP method POST and URL path /checkout*, and delete it after the incident.
    • D. Enable active tracing for the application in the Lambda console.
  2. A developer writes a script that must print the full segment documents of every trace in the last hour that has the annotation order_status = "failed". Which TWO X-Ray API operations should the script call? (Select TWO.)

    • A. GetTraceSummaries with the filter expression annotation[order_status] = "failed".
    • B. PutTraceSegments for the time range of the last hour.
    • C. GetSamplingTargets for the service that records the annotation.
    • D. BatchGetTraces with the trace IDs returned by the first call, in groups of up to five.
    • E. GetServiceGraph for the last hour.
Answers
  1. C. A high-priority centralized rule overrides the default for that route on every instance immediately, with no deployment. A needs a redeploy and makes each instance sample independently; B raises sampling for all traffic; D applies to Lambda functions, not EC2.
  2. A, D. GetTraceSummaries filters by annotation and returns trace IDs; BatchGetTraces returns the segment documents for those IDs, at most five per call. B uploads segments; C is used by SDKs to get sampling quotas; E returns the graph, not segments.

10. CloudTrail auditing and choosing the right tool

Concept

Exam facts

Question in the stem Tool
Is latency or the error rate rising, and can it page me? CloudWatch metrics and alarms
What did the application log for this request or time window? CloudWatch Logs, Logs Insights
Which service or downstream call makes a request slow or fail? X-Ray traces and trace map
Who deleted or changed this resource, from where, with which credentials? CloudTrail (Event history or a trail)
Run something when a resource changes state or an API is called EventBridge rule (AWS or CloudTrail events)
Is the endpoint up even when no users are active? CloudWatch Synthetics canary
What did this resource's configuration look like last Tuesday? AWS Config (outside this module)

Developer angle

Who deleted the table yesterday (no trail needed for the last 90 days)?

aws cloudtrail lookup-events --start-time 2026-10-11T00:00:00Z --max-results 50 \
  --lookup-attributes AttributeKey=EventName,AttributeValue=DeleteTable \
  --query 'Events[].[EventTime,Username,CloudTrailEvent]'

A validated multi-Region trail with selected data events, Insights and CloudWatch Logs delivery:

aws cloudtrail create-trail --name audit --s3-bucket-name audit-logs-111122223333 \
  --is-multi-region-trail --enable-log-file-validation --kms-key-id alias/cloudtrail
aws cloudtrail start-logging --name audit
aws cloudtrail put-event-selectors --trail-name audit --advanced-event-selectors file://selectors.json
aws cloudtrail put-insight-selectors --trail-name audit \
  --insight-selectors '[{"InsightType":"ApiCallRateInsight"},{"InsightType":"ApiErrorRateInsight"}]'
aws cloudtrail update-trail --name audit \
  --cloud-watch-logs-log-group-arn arn:aws:logs:eu-west-1:111122223333:log-group:cloudtrail/audit:* \
  --cloud-watch-logs-role-arn arn:aws:iam::111122223333:role/CloudTrail_CloudWatchLogs_Role
aws cloudtrail validate-logs --trail-arn arn:aws:cloudtrail:eu-west-1:111122223333:trail/audit \
  --start-time 2026-10-01T00:00:00Z

selectors.json (all management events, plus writes to one bucket's objects):

[
  {"Name": "Management events", "FieldSelectors": [{"Field": "eventCategory", "Equals": ["Management"]}]},
  {"Name": "Object writes in orders-uploads", "FieldSelectors": [
    {"Field": "eventCategory", "Equals": ["Data"]},
    {"Field": "resources.type", "Equals": ["AWS::S3::Object"]},
    {"Field": "readOnly", "Equals": ["false"]},
    {"Field": "resources.ARN", "StartsWith": ["arn:aws:s3:::orders-uploads/"]}]}
]

React to one dangerous call within minutes (EventBridge rule on the default bus, SNS target):

{
  "source": ["aws.dynamodb"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {"eventSource": ["dynamodb.amazonaws.com"], "eventName": ["DeleteTable"]}
}

Alarm on unauthorized calls through the trail's log group:

aws logs put-metric-filter --log-group-name cloudtrail/audit --filter-name unauthorized-calls \
  --filter-pattern '{ ($.errorCode = "*UnauthorizedOperation") || ($.errorCode = "AccessDenied*") }' \
  --metric-transformations metricName=UnauthorizedCalls,metricNamespace=Audit,metricValue=1,defaultValue=0

Traps

Practice questions

  1. An Amazon DynamoDB table was deleted yesterday. The account has no CloudTrail trail. The team must identify the IAM principal that deleted it, with the LEAST effort. What should the developer do?

    • A. Search CloudTrail Event history (aws cloudtrail lookup-events) for the DeleteTable event name and read its userIdentity.
    • B. Open the X-Ray trace map for the application that used the table.
    • C. Run a CloudWatch Logs Insights query against the table's log group.
    • D. Create a trail now and query its S3 objects with Amazon Athena.
  2. A security team wants an email within minutes whenever any IAM role's trust policy is changed (UpdateAssumeRolePolicy), and must keep the full record of such API calls for 7 years. Which TWO actions meet these requirements? (Select TWO.)

    • A. Rely on CloudTrail Event history, which can retain events for up to 7 years.
    • B. Enable CloudTrail Insights for API call rate on the account.
    • C. Create an EventBridge rule on the default bus that matches AWS API Call via CloudTrail events with eventSource iam.amazonaws.com and eventName UpdateAssumeRolePolicy, with an SNS topic as target.
    • D. Create an X-Ray group with a filter expression for IAM calls.
    • E. Create a multi-Region trail that delivers to an S3 bucket with a lifecycle policy (or Object Lock) that keeps objects for 7 years.
Answers
  1. A. Event history holds 90 days of management events without any trail, and DeleteTable is a management event. B and C don't record API callers; D only captures events from now on.
  2. C, E. An EventBridge rule on the CloudTrail API-call event reacts in near real time (with an active trail), and a trail to S3 with lifecycle or Object Lock gives multi-year retention. A is wrong (90 days); B detects unusual rates, not one specific call; D traces application requests, not IAM API calls.

Quick decision rules

Metrics and metrics from logs (§1–§2)

Logs (§3–§4)

Alarms and canaries (§5)

EventBridge (§6–§7)

Tracing (§8–§9)

Audit and tool choice (§10)

Changed vs older material

Learn the Current column; older practice material may still show the Course / older material value. Rows are proposed for notes/current-facts.md after confirmation (some already exist there under the ec2 or sqs-sns-kinesis modules).

Topic Course / older material Current (verified 2026-10-12) Source
§1 · PutMetricData request limits 20 metrics and 40 KB per call 1,000 metrics and 1 MB per call (gzip allowed), 150 values per Values array, 30 dimensions per metric AWS docs
§2–§3 · Maximum log event size (EMF included) 256 KB 1 MB since 2025-04-02 (PutLogEvents and the OTLP endpoint) What's New
§3 · PutLogEvents sequence token and rate Each call needs the previous nextSequenceToken; InvalidSequenceTokenException; 5 requests/s per log stream Token ignored, parallel writes to one stream allowed, per-account throttle (5,000 requests/s default, adjustable) AWS docs
§3 · CloudWatch Logs agent Valid way to push logs from servers Deprecated, doesn't work with IMDSv2-only instances; use the unified CloudWatch agent AWS docs
§4 · Logs Insights query languages One purpose-built query language Logs Insights QL, OpenSearch PPL and OpenSearch SQL AWS docs
§4 · Logs Insights concurrency and result size 30 concurrent queries; 10,000 results 100 concurrent QL queries (15 PPL/SQL) since 2026-03-09 (most Regions); up to 100,000 QL results since 2026-05-15 (10,000 per page) AWS docs
§4 · Subscription filters per log group 2 5 per log group, plus 1 account-level subscription filter per Region (account-level filters since 2024-01-11) AWS docs
§4 · Firehose and Kinesis Data Analytics names Kinesis Data Firehose; Kinesis Data Analytics Amazon Data Firehose (rename only, 2024-02-09); Kinesis Data Analytics for SQL discontinued → Managed Service for Apache Flink What's New
§5 · High-resolution alarm periods 10 or 30 seconds 10, 20 or 30 seconds, or any multiple of 60 AWS docs
§5 · Alarm action targets SNS, EC2 actions, Auto Scaling Also Lambda (2023-12-22), Systems Manager OpsItems and Incident Manager, CloudWatch investigations AWS docs
§5 · Composite alarm rules and actions AND/OR only; SNS notifications only AND, OR, NOT, AT_LEAST (2025-11-11); SNS, Lambda, OpsItems/incidents, investigations; still no EC2/Auto Scaling AWS docs
§5 · Synthetics languages and browsers Node.js or Python, headless Chrome Node.js (Puppeteer, Playwright), Python (Selenium), Java (2025-05-28); Chrome and Firefox (Selenium: Chrome) AWS docs
§5 · Synthetics blueprints Six blueprints Adds Multi checks (up to 10 HTTP, DNS, SSL, TCP checks, 2025-10-22) AWS docs
§6 · Scheduling EventBridge scheduled rules for cron jobs Scheduled rules are legacy (default bus, UTC); EventBridge Scheduler recommended AWS docs
§6 · PutEvents size 256 KB per request 1 MB per request to default/Classic buses since 2026-01-29 (not all Regions at launch) AWS docs
§6 · Lambda, SNS, SQS target permissions Resource-based policy required Resource-based policy or IAM execution role (2025-03-11) AWS docs
§7 · Custom event bus types One kind of custom bus New Custom Event Bus (subscribers, 1–365-day retention, RAM sharing, eventsv2, 2026-09-24) next to Custom Event Bus - Classic AWS docs
§7 · Cross-account delivery Always through the other account's event bus Also direct to SQS, SNS, Lambda, Kinesis, API Gateway targets in the same Region (2025-01-21; execution role in the bus account + target resource policy that allows the bus account); new cross-account bus targets need an IAM role (2023-03-02) What's New · AWS docs
§8 · X-Ray SDK and daemon status Standard, fully supported approach Maintenance mode since 2026-02-25 (security fixes only) AWS docs
§8 · Recommended tracing stack ADOT optional alternative OpenTelemetry (OTel SDKs or ADOT) + CloudWatch agent 1.300025.0+ or OTel Collector; Lambda layer for OpenTelemetry AWS docs
§10 · Single-Region trails Console choice: all Regions or one Region Console creates multi-Region trails only; CLI/API default to single-Region and need start-logging AWS docs
§10 · Data event types S3 object-level activity and Lambda Invoke Many resource types via advanced event selectors (DynamoDB, SNS, SQS, Kinesis, CloudWatch PutMetricData…) AWS docs
§10 · CloudTrail Insights scope Baseline of management events, analysis of write events API call rate (write management) + API error rate (read/write management); data-event Insights since 2025-11-20 (trails) AWS docs
§10 · CloudTrail Lake Recommended for SQL over CloudTrail events Closed to new customers since 2026-05-31; AWS points to CloudWatch AWS docs
§10 · Read-only API events in EventBridge Never delivered Matched by rules in state ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS (2023-11-17; CLI or CloudFormation only) AWS docs
Overview · CloudWatch Evidently Feature flags and A/B experiments with Evidently Discontinued 2025-10-17; AppConfig feature flags; AppConfig experimentation GA 2026-07-01 AWS docs