βοΈ AWS Architecture β Staff-Level Interview Questions¶
8 questions covering the Well-Architected Framework, multi-Region DR, migration strategy, cost governance, microservices, serverless vs containers, cloud-native patterns and resilience engineering. Each answer leads with the 30-second version, then the mechanism, trade-offs, failure modes and what interviewers probe next. Service facts checked against AWS documentation, October 2026.
Table of Contents¶
- AWS Well-Architected Framework: The Six Pillars
- Multi-Region Architecture & Disaster Recovery
- Cloud Migration Strategies: The 6 Rs
- Cost Optimization Architecture at Scale
- Microservices Architecture Patterns on AWS
- Serverless vs Containers: Architecture Decision
- Cloud-Native Design Patterns: Strangler Fig, CQRS, Saga
- Resilience Engineering & Chaos Engineering
1. AWS Well-Architected Framework: The Six Pillars¶
Q: "Your CTO wants a formal Well-Architected Framework review of a production system processing $10M/month in transactions. Walk through the six pillars, the key questions you'd ask in each, and how you'd prioritize remediation. How do you operationalize WA reviews across 50 microservices?"
What They're Really Testing: Whether you understand the Well-Architected Framework as an operational tool β not just theory β and can drive continuous improvement at scale across an organization.
Answer¶
30-second answer
Six pillars: Operational Excellence, Security, Reliability, Performance Efficiency, Cost Optimization and Sustainability (added December 2021). A review is a structured conversation per workload (a set of components that deliver business value together, not each microservice) that produces high- and medium-risk issues (HRIs/MRIs). For a payments system, prioritise by blast radius on money and data: security and reliability HRIs first, then operational gaps that slow recovery, then cost and efficiency. Operationalise with the Well-Architected Tool (custom lenses, review templates, milestones), automated evidence from Security Hub CSPM, Config and Trusted Advisor, and a recurring cadence tied to architecture changes, not a one-off audit.
What to ask per pillar (a payments workload):
| Pillar | Questions that find real risk | Evidence |
|---|---|---|
| Operational Excellence | How do you know it's healthy right now? How do you deploy and roll back? When did you last run the incident runbook? | SLO dashboards, deployment frequency, change failure rate, MTTR, post-incident reviews |
| Security | Who can move money or read card data, and how do you know? How are secrets and keys managed? How fast do you detect a leaked credential? | IAM Access Analyzer, CloudTrail, GuardDuty/Security Hub findings, KMS key policies |
| Reliability | What happens when an AZ, a dependency or the database fails? What are RTO/RPO and when were they last tested? Are retries idempotent? | Multi-AZ design, quotas headroom, DR test results, FIS experiments |
| Performance Efficiency | What limits throughput first? How do you load test? | Load test reports, p99 under peak, saturation metrics |
| Cost Optimization | What's the cost per transaction and how is it trending? What's idle? | Tagged cost allocation, unit costs, Savings Plans coverage |
| Sustainability | Are you using efficient instance types and scaling to demand? What data do you keep that you don't need? | Utilisation, Graviton share, storage lifecycle, Customer Carbon Footprint Tool |
Lenses add domain-specific questions (Serverless, SaaS, Financial Services, Container Build, Generative AI and others); use the Financial Services lens here.
Prioritising remediation:
- Rank HRIs by likelihood Γ impact, with impact expressed in business terms (lost transactions per minute, regulatory exposure).
- Typical top findings in payments systems: overly broad IAM (
*on production data), untested DR, retries without idempotency keys (double charges), single-AZ dependencies hidden in "managed" components, no alarms on queue age or DLQs. - Fix HRIs within a fixed window (e.g. one sprint), MRIs within a quarter, and record decisions to accept risk explicitly with an owner.
Operationalising across 50 microservices:
- Group services into a handful of workloads (payments core, ledger, notifications) and review those; service-level checks are automated rather than questionnaire-based.
- WA Tool: review templates pre-fill org-wide answers (shared platform controls), profiles set business priorities, custom lenses encode internal standards, milestones snapshot progress. The WA Tool API exports risks to your tracker.
- Continuous evidence: Security Hub CSPM controls, Config conformance packs and Trusted Advisor checks feed the review, so the questionnaire focuses on design and process.
- Cadence: on major architecture changes and at least annually per workload, with a light quarterly risk check. Track the HRI count and age, not a vanity score.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| Pillar depth | Asks evidence-seeking questions per pillar, tied to the business |
| Prioritization | Ranks HRIs by business impact and tracks accepted risk explicitly |
| Operationalization | Reviews per workload with templates, lenses and recurring cadence |
| Automation | Uses WA Tool API and continuous evidence from Security Hub, Config, Trusted Advisor |
π¬ Animated Sequence Diagram¶
π¬ Animated Well-Architected Framework Six Pillars β Operational Excellence, Security, Reliability, Performance Efficiency, Cost Optimization, and Sustainability β Click βΆ to play/pause. Created with Remotion.
2. Multi-Region Architecture & Disaster Recovery¶
Q: "Design a multi-region architecture for a financial services platform with RPO of 1 second and RTO of 5 minutes. 99.999% availability required. Compare active-passive vs active-active strategies. How do you handle data replication across regions with strong consistency requirements?"
What They're Really Testing: Whether you understand the operational and architectural trade-offs of multi-region deployment β the hard realities of cross-region replication lag, DNS propagation, and failover complexity.
Answer¶
30-second answer
99.999% is ~5 minutes of downtime a year, so failover must be pre-provisioned, rehearsed and mostly automated. RPO 1 s rules out backup/restore and pilot light; it means continuous replication with bounded lag (Aurora Global Database with an RPO limit, DynamoDB global tables) or synchronous multi-Region writes (DynamoDB MRSC, Aurora DSQL) where you need RPO 0. An RTO of 5 minutes fits warm standby with a scripted, operator-triggered Region switch (Route 53 ARC). Active-active is only worth it when you partition data by home Region or use a multi-Region strongly consistent store; otherwise you're trading failover time for conflict resolution bugs.
DR strategies:
| Strategy | RPO | RTO | Standby cost | Notes |
|---|---|---|---|---|
| Backup & restore | Hours (backup interval) | Hours | Lowest | AWS Backup cross-Region copies; IaC to rebuild |
| Pilot light | Minutes or less (data replicated) | Tens of minutes | Low | Data live, compute off; AWS Elastic Disaster Recovery for server workloads |
| Warm standby | Seconds | Minutes | Medium | Scaled-down full stack, scale up on failover |
| Active-active (multi-site) | Seconds to zero | Near zero for reads; seconds for writes | Highest | Requires data partitioning or multi-Region consistency |
Warm standby for RPO 1 s / RTO 5 min:
us-east-1 (primary) us-west-2 (standby)
Route 53 ARC routing control: ON routing control: OFF
ALB β ECS (100 tasks) ALB β ECS (20 tasks, pre-scaled minimum)
Aurora Global DB writer βββstorage replββββΊ Aurora secondary cluster (readers)
DynamoDB global table βββββ MREC ββββββΊ replica
ElastiCache Global Datastore βββββββββββββΊ replica (warm cache)
S3 (CRR + RTC) ββββββββββββββββββΊ bucket
SQS / in-flight work (not replicated: rebuild from DB/outbox state)
Failover runbook (ARC Region switch or Step Functions), in this order:
- Decide (T+0β1 min): a human (or a strict multi-signal rule) declares the Region impaired. Fully automatic failover on a single health check risks flapping and split brain.
- Fence the old primary: stop writers (routing control off, app write-disable flag) so nothing commits there after promotion.
- Promote data (T+1β2): Aurora Global Database failover (unplanned; RPO = lag at that moment) or switchover (planned; RPO 0). Use the global writer endpoint so apps don't need new connection strings.
- Scale standby compute (pre-warmed minimums so you're not waiting on capacity).
- Shift traffic (T+3β4): ARC routing control on in us-west-2; DNS TTLs of 60 s or less; or Global Accelerator traffic dials for near-instant shifts.
- Verify with synthetic transactions; reconcile the replication-lag window (idempotency keys make replays safe).
Region failover runbook order: decide, fence the old primary, promote data, scale, shift traffic, verify.
flowchart LR
D["1. Decide: Region impaired"] --> F["2. Fence old primary"]
F --> P["3. Promote Aurora and data stores"]
P --> S["4. Scale standby compute"]
S --> T["5. Shift traffic: ARC routing control"]
T --> V["6. Verify and reconcile lag window"]
Making RPO 1 s real: Aurora Global Database lag is typically under a second, not guaranteed. Aurora PostgreSQL's rds.global_db_rpo parameter makes the primary block commits when secondaries fall further behind than the limit, trading availability for a hard RPO. DynamoDB MREC typically replicates in under a second with last-writer-wins; for balances use MRSC (RPO 0, exactly three Regions, higher write latency, no transactions).
Active-active options:
| Approach | Consistency | Cost of the choice |
|---|---|---|
| Partition by home Region (user/tenant pinned to a Region) | Strong within the home Region | Re-homing users, cross-Region reads for shared data |
| DynamoDB MREC | Eventual, last writer wins per item | Conflicts silently overwrite; design commutative or idempotent writes |
| DynamoDB MRSC / Aurora DSQL | Strong across Regions | Higher write latency (cross-Region round trips), feature limits |
| CRDTs / custom merge | Convergent | Application complexity |
Reads stay local; route users to their nearest healthy Region with Route 53 latency records or Global Accelerator.
Testing: run Region evacuation game days quarterly (ARC Region switch plans, FIS cross-Region connectivity scenario), measure real RTO/RPO, and keep quotas (instance limits, concurrency, IPs) raised in the standby Region; failover fails most often on quotas and stale config.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| DR strategies | Can quantitatively compare backup/pilot/warm/active-active with RPO, RTO, cost |
| Failover sequence | Fences, promotes data, scales, then shifts traffic, with timing for each step |
| Cross-region data | Uses Aurora Global DB (with RPO limit), DynamoDB global tables (MREC vs MRSC), Global Datastore |
| Active-active | Understands conflict resolution (LWW, CRDTs, home-Region partitioning) and idempotent writes |
π¬ Animated Sequence Diagram¶
π¬ Animated Multi-Region Disaster Recovery β Aurora Global DB replication, Route53 failover, and RPO 1s/RTO 5min active-passive strategy β Click βΆ to play/pause. Created with Remotion.
3. Cloud Migration Strategies: The 6 Rs¶
Q: "Your company has 200 on-premises servers running a mix of legacy .NET applications, Java microservices, and Oracle databases. The CFO wants 40% cost reduction in 18 months. Walk through the migration strategy: how do you assess, prioritize, and execute? What are the 6 Rs and when do you use each?"
What They're Really Testing: Whether you understand cloud migration as a business transformation β not just a technical lift-and-shift β and can navigate the trade-offs between speed, cost, and risk.
Answer¶
30-second answer
AWS now uses 7 Rs: Retire, Retain, Rehost, Relocate (added for VMware Cloud on AWS), Replatform, Repurchase, Refactor. Assess first (discovery data on utilisation and dependencies, plus a business case), then move in waves grouped by dependency, starting with low-risk rehosts that build the factory. Savings come mostly from right-sizing during migration, retiring what nobody uses, licence changes (Oracle/SQL Server/Windows), and commitments, not from the move itself. A 40% cut in 18 months is achievable if you plan those levers up front and track unit costs.
The 7 Rs:
| R | What | When | Typical tooling |
|---|---|---|---|
| Retire | Switch it off | Unused or duplicate apps (often 10%+ of a portfolio) | Discovery data, owner sign-off |
| Retain | Keep on-prem for now | Recent hardware investment, compliance, pending replacement | Revisit later |
| Rehost | Lift and shift to EC2 | Speed matters, app works as is | AWS Application Migration Service (MGN) |
| Relocate | Move VMware VMs without converting them | Large VMware estates, minimal change | VMware Cloud on AWS / VMware HCX |
| Replatform | Small changes for managed services | Self-managed DB β RDS, app server β containers | DMS, MGN with modernisation options |
| Repurchase | Move to SaaS | Non-differentiating apps (CRM, HR, ITSM) | Vendor tools |
| Refactor | Re-architect | Apps needing scale, agility or licence escape | AWS Transform (.NET, mainframe, VMware), containers/serverless |
Choosing an R for each application in the portfolio.
flowchart TD
A[Application] --> U{"Still used?"}
U -->|no| RT[Retire]
U -->|yes| K{"Must stay on-prem for now?"}
K -->|yes| RN[Retain]
K -->|no| SA{"Non-differentiating, SaaS exists?"}
SA -->|yes| RP[Repurchase]
SA -->|no| VM{"VMware estate, minimal change?"}
VM -->|yes| RL[Relocate]
VM -->|no| CH{"Needs re-architecture?"}
CH -->|yes| RF[Refactor]
CH -->|"small tweaks, managed services"| RPL[Replatform]
CH -->|"works as is, speed matters"| RH[Rehost]
AWS Server Migration Service and CloudEndure Migration were retired in favour of MGN, and AWS Migration Hub stopped accepting new customers in November 2025; its planning features moved into AWS Transform (agentic AI assistance for .NET porting, mainframe and VMware migrations).
Assessment:
- Discovery: AWS Application Discovery Service agents/collectors or existing CMDB/monitoring data β utilisation (CPU p95, memory), dependencies (network connections), software inventory.
- Business case: Migration Evaluator or equivalent, using actual utilisation for right-sized targets and licence-included vs BYOL options.
- Prioritise with a matrix of business value, technical complexity and dependency coupling. Move tightly coupled apps together in one wave; chatty cross-premises calls over a VPN are where migrations stall.
Example plan for 200 servers (illustrative):
| Wave | Months | Content | Strategy |
|---|---|---|---|
| 0 | 1β2 | Landing zone, network (Direct Connect), identity, migration factory | β |
| 1 | 3β5 | 30 low-risk stateless apps; retire 20 servers | Rehost with right-sizing |
| 2 | 6β11 | .NET apps β Windows containers or .NET 8 on Linux; SQL Server β RDS | Replatform/refactor (AWS Transform for .NET) |
| 3 | 9β15 | Oracle β Aurora PostgreSQL for apps that can change; RDS for Oracle (BYOL) for those that can't | Replatform/refactor with DMS |
| 4 | 15β18 | Remaining apps, data centre exit | Rehost/retain decisions |
Where the 40% comes from:
- Right-sizing at migration time (on-prem servers commonly run at low average CPU).
- Retiring idle and duplicate servers.
- Licence: Windows β Linux for .NET 8, Oracle β PostgreSQL, SQL Server Enterprise β Standard where features allow.
- Commitments: Compute Savings Plans and Database Savings Plans once usage stabilises.
- Elasticity: scale-to-demand and non-prod schedules.
- Exit costs avoided: hardware refresh, data centre lease, power.
Track it: tag every migrated resource with the app and wave (MGN can tag automatically), measure monthly run-rate vs the on-prem baseline, and watch for the "double bubble" of paying for both environments during overlap. AWS's Migration Acceleration Program (MAP) credits can offset migration costs.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| 7 Rs fluency | Can explain each R (including Relocate), when to use it, and current tooling |
| Assessment process | Uses discovery data to catalog servers, dependencies, and utilization |
| Prioritization | Creates dependency-aware wave plan (quick wins first, strategic refactors later) |
| Cost optimization | Identifies where savings actually come from and tracks them against a baseline |
π¬ Animated Sequence Diagram¶
π¬ Animated Cloud Migration 6 Rs β Retire, Retain, Rehost, Replatform, Refactor, Repurchase with prioritization matrix (AWS has since added a seventh R, Relocate) β Click βΆ to play/pause. Created with Remotion.
4. Cost Optimization Architecture at Scale¶
Q: "Your AWS bill is $2M/month and growing 15% month over month. Your CFO wants a cost optimization strategy that doesn't sacrifice growth. Design a cloud cost governance framework covering tagging, budgets, anomaly detection, and automated remediation. How do you build a culture of cost awareness?"
What They're Really Testing: Whether you understand cloud cost management as a cultural and operational discipline β not just a one-time rightsizing exercise β and can design a governance framework that scales with the organization.
Answer¶
30-second answer
15% month over month is 5x a year; first ask whether revenue is growing with it. Govern with unit economics (cost per transaction or per customer), not total spend. Three layers: visibility (account-per-team structure plus enforced tags, CUR 2.0 data in Athena/QuickSight, showback/chargeback), guardrails (budgets with alerts and actions, Cost Anomaly Detection per account and tag, SCPs/tag policies on expensive choices), and optimisation loops (Cost Optimization Hub and Compute Optimizer recommendations, commitment management, architecture changes). Automate shutdown only in non-prod; in prod, automate detection and routing to owners.
Visibility:
- Accounts are the cleanest cost boundary (one team or product per account); tags handle what accounts can't (shared clusters, per-feature cost).
- Required tags (
team,service,env) enforced with tag policies (allowed values) and SCP conditions onaws:RequestTagfor create calls; activate them as cost allocation tags. Untagged spend is reported weekly as a team's debt. - Shared costs (EKS clusters, data platforms) allocated with split cost allocation data for EKS/ECS, or by a documented formula.
- Data: CUR 2.0 via Data Exports into S3 β Athena/QuickSight (or the CUDOS dashboards); Cost Explorer for ad-hoc questions.
Guardrails:
| Control | Use |
|---|---|
| AWS Budgets (per account, per tag) | Alerts on actual and forecasted spend; budget actions can apply an IAM/SCP policy or stop EC2/RDS in non-prod |
| Cost Anomaly Detection | ML monitors per service, account, cost category or tag; alerts to SNS/Slack/email (immediate, daily or weekly) with root-cause dimensions |
| SCPs / declarative policies | Deny unapproved instance families or Regions in sandboxes, require tags on create |
| Service Quotas | Keep quotas near expected use in sandboxes as a blast-radius cap |
Optimisation loop:
- Cost Optimization Hub consolidates recommendations (right-sizing, Graviton, idle resources, Savings Plans/RI purchases) across accounts and ranks them by savings, de-duplicating overlaps.
- Compute Optimizer for EC2, ASGs, EBS, Lambda, ECS on Fargate, RDS.
- Commitments: Compute Savings Plans for the stable compute baseline, Database Savings Plans (Dec 2025, up to 35%) or RIs for databases, laddered quarterly so commitments track growth. Target high utilisation (>95%) and rising coverage.
- Architecture: Graviton, Spot for interruptible work, gp3 instead of gp2, S3 lifecycle/Intelligent-Tiering, VPC endpoints to cut NAT processing, cross-AZ traffic reduction, log retention and sampling (CloudWatch Logs is a frequent surprise).
Anomaly handler (SNS-subscribed Lambda):
import json
import boto3
ecs = boto3.client("ecs")
sns = boto3.client("sns")
def handler(event, context):
msg = json.loads(event["Records"][0]["Sns"]["Message"]) # Cost Anomaly Detection alert
impact = msg["impact"]["totalImpact"]
causes = msg.get("rootCauses", []) # service, region, account, usage type
owners = route_to_owners(causes) # via account β team mapping
for owner in owners:
sns.publish(TopicArn=owner.topic_arn, Subject=f"Cost anomaly ${impact:,.0f}",
Message=json.dumps({"anomalyId": msg["anomalyId"], "rootCauses": causes}))
# Automatic action only for non-production accounts with an explicit opt-in tag
for svc in non_prod_services_opted_in(causes):
ecs.update_service(cluster=svc.cluster, service=svc.name, desiredCount=0)
Stopping production resources because spend spiked is how a successful launch becomes an outage. Make the default action "page the owner with root cause", and reserve automatic stops for sandboxes and non-prod.
Culture:
- Each team sees its own spend and unit cost on its dashboard; cost is reviewed in the same forum as reliability.
- Engineers estimate the cost of a design in design reviews (data transfer, request counts and log volume are where estimates miss).
- Celebrate removed waste the same way as shipped features; give teams the savings to reinvest.
- A central FinOps function owns commitments and tooling; teams own their usage.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| Governance framework | Designs visibility, guardrails and optimisation loops around unit cost |
| Anomaly detection | Uses ML-based detection that routes to owners; automates only safe actions |
| Tagging strategy | Enforces required tags via tag policies/SCPs, uses accounts as primary boundary |
| Cost culture | Implements team dashboards, design-time cost estimates, shared ownership |
π¬ Animated Sequence Diagram¶
π¬ Animated Cloud Cost Governance Framework β tagging, budgets, anomaly detection, rightsizing, and cost culture β Click βΆ to play/pause. Created with Remotion.
5. Microservices Architecture Patterns on AWS¶
Q: "Your team is migrating a monolithic .NET application to microservices on AWS. Design the architecture covering: service decomposition, inter-service communication, data management, and observability. How do you handle distributed transactions? How do you manage service discovery?"
What They're Really Testing: Whether you understand the real challenges of microservices β data consistency, service discovery, observability, and deployment complexity β not just the theoretical benefits.
Answer¶
30-second answer
Decompose by bounded context and team ownership, extract incrementally with the strangler fig, and give each service its own data store. Default to asynchronous events between services (EventBridge/SNS+SQS, published via a transactional outbox) and keep synchronous calls for queries that need an immediate answer, with timeouts, retries with backoff and circuit breakers. Replace distributed transactions with sagas: Step Functions orchestration when the flow has many steps or needs audit, choreography when it's short. Discovery is ECS Service Connect, Kubernetes services, or VPC Lattice across accounts. Observability is OpenTelemetry traces, structured logs with trace IDs, and RED metrics per service.
Decomposition:
API Gateway / ALB (routing, auth, throttling)
βββββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ¬ββββββββββββββββ
β Orders β Payments β Inventory β Notifications β
β DynamoDB β Aurora PG β DynamoDB β DynamoDB β
β outboxβStream β outbox table β β β
βββββββββ¬ββββββββ΄βββββββ¬ββββββββ΄βββββββ¬ββββββββ΄ββββββββ¬ββββββββ
ββββββββββββββββ΄ββ EventBridge bus ββββββββββββ
- Data ownership: no shared tables. Other services get data via APIs or events and keep their own read copies.
- Size: a service should be owned by one team and deployable alone; if two services always deploy together, they're one service.
- Start with the seams that change most often or need to scale differently; leave the stable core in the monolith longer.
Communication patterns:
| Pattern | Use | AWS building blocks | Watch out for |
|---|---|---|---|
| Async event | State changes others react to | EventBridge, SNSβSQS, Kinesis/MSK for streams | At-least-once delivery β idempotent consumers; schema evolution |
| Async command | "Do this work" | SQS queue owned by the receiver | Backpressure, DLQs |
| Sync request/response | Queries needing an answer now | HTTP/gRPC via Service Connect, VPC Lattice, ALB | Latency chains, cascading failure; set timeouts below the caller's |
| Workflow | Multi-step business process | Step Functions | State machine becomes a coupling point; version it |
Publish events reliably with a transactional outbox: write the business row and the event row in one DB transaction, then relay (DynamoDB Streams β EventBridge Pipes, or Debezium/DMS CDC for relational DBs). Without it, a crash between "commit" and "publish" loses or invents events.
Transactional outbox: the business row and event row commit together, a relay publishes afterwards.
sequenceDiagram
participant S as Order service
participant DB as Service DB
participant R as Relay (Streams or CDC)
participant B as EventBridge bus
S->>DB: One transaction: write order and outbox event
DB-->>S: Commit
R->>DB: Read new outbox events
R->>B: Publish event
B-->>R: Ack
Note over R,B: At-least-once, so consumers must be idempotent
Orchestrated saga (Step Functions):
{
"Comment": "Order saga with compensations",
"StartAt": "ProcessPayment",
"States": {
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": { "FunctionName": "process-payment", "Payload.$": "$" },
"Retry": [{ "ErrorEquals": ["Lambda.TooManyRequestsException", "States.Timeout"],
"IntervalSeconds": 1, "BackoffRate": 2, "MaxAttempts": 3, "JitterStrategy": "FULL" }],
"Catch": [{ "ErrorEquals": ["States.ALL"], "ResultPath": "$.error", "Next": "CancelOrder" }],
"ResultPath": "$.payment",
"Next": "ReserveInventory"
},
"ReserveInventory": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": { "FunctionName": "reserve-inventory", "Payload.$": "$" },
"Catch": [{ "ErrorEquals": ["States.ALL"], "ResultPath": "$.error", "Next": "RefundPayment" }],
"ResultPath": "$.inventory",
"Next": "ConfirmOrder"
},
"ConfirmOrder": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": { "FunctionName": "confirm-order", "Payload.$": "$" },
"Catch": [{ "ErrorEquals": ["States.ALL"], "ResultPath": "$.error", "Next": "ReleaseInventory" }],
"End": true
},
"ReleaseInventory": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke",
"Parameters": { "FunctionName": "release-inventory", "Payload.$": "$" },
"Next": "RefundPayment" },
"RefundPayment": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke",
"Parameters": { "FunctionName": "refund-payment", "Payload.$": "$" },
"Next": "CancelOrder" },
"CancelOrder": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke",
"Parameters": { "FunctionName": "cancel-order", "Payload.$": "$" },
"Next": "Failed" },
"Failed": { "Type": "Fail", "Error": "OrderSagaFailed" }
}
}
The order saga from the state machine above: failures route through compensations in reverse order.
stateDiagram-v2
[*] --> ProcessPayment
ProcessPayment --> ReserveInventory: ok
ProcessPayment --> CancelOrder: error
ReserveInventory --> ConfirmOrder: ok
ReserveInventory --> RefundPayment: error
ConfirmOrder --> [*]: ok
ConfirmOrder --> ReleaseInventory: error
ReleaseInventory --> RefundPayment
RefundPayment --> CancelOrder
CancelOrder --> Failed
Failed --> [*]
- Compensations run in reverse order of completed steps and must themselves be idempotent and retried until they succeed (a refund that fails needs alerting, not silence).
- Pass a saga ID / idempotency key to every participant so retries don't double-charge.
- Step Functions retries only what you declare in
Retry; Standard workflows suit long-running sagas (up to a year, exactly-once state transitions), Express suits high-volume short ones.
Service discovery:
- ECS Service Connect (managed proxy, Cloud Map namespace) inside ECS; Kubernetes Services/DNS inside EKS.
- VPC Lattice for service-to-service traffic across VPCs and accounts, with IAM auth policies and no need for peering or non-overlapping CIDRs.
- Plain Cloud Map DNS when you just need names; mind client DNS caching.
Observability:
- Traces: OpenTelemetry (ADOT or the CloudWatch agent) to X-Ray / CloudWatch Application Signals. The X-Ray SDKs and daemon entered maintenance mode in February 2026 (end of support February 2027), so new code should instrument with OpenTelemetry. X-Ray's default sampling records the first request each second and 5% of the rest; tail-based sampling of errors is worth adding.
- Logs: structured JSON with trace ID, request ID, tenant; central log account; retention policies set deliberately.
- Metrics: RED (rate, errors, duration) per endpoint, plus business metrics (orders/min) and queue age for async paths. SLOs with error budgets per service (Application Signals supports SLOs).
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| Decomposition | Uses bounded contexts, Strangler Fig pattern, data autonomy per service |
| Async-first | Prefers events with an outbox; uses sagas with idempotent compensations |
| Service discovery | Chooses Service Connect, Kubernetes services or VPC Lattice appropriately |
| Observability | Implements OpenTelemetry tracing, structured logs with correlation IDs, RED metrics and SLOs |
6. Serverless vs Containers: Architecture Decision¶
Q: "Your team is building a new data processing platform with unpredictable traffic: 0-50K requests/second. Half the workload is latency-sensitive (API responses <100ms), half is batch processing (can take minutes). Walk through the decision framework for serverless (Lambda + Fargate) vs containers (ECS/EKS). When would you use each, and how do you combine them?"
What They're Really Testing: Whether you have a pragmatic decision framework β not dogmatic about serverless or containers β and can match the right compute model to the workload's actual requirements.
Answer¶
30-second answer
Decide on utilisation, latency and constraints, not fashion. Lambda wins for spiky or low average utilisation, event-driven glue and teams that want zero infrastructure; it gets expensive at sustained high request rates, and cold starts plus a 15-minute limit rule it out for some work. Containers on ECS/EKS (Fargate for no-node operations, EC2 for price, GPUs and tuning) win for steady high throughput, long-running or stateful processes, and special hardware. For 0β50K req/s with a <100 ms API: put the API on containers with autoscaling (or Lambda with provisioned concurrency if traffic is truly bursty and near zero most of the time), and batch on Fargate/EC2 Spot or AWS Batch fed by SQS.
Decision factors:
| Factor | Lambda | Fargate (ECS/EKS) | ECS/EKS on EC2 |
|---|---|---|---|
| Max duration | 15 minutes | Unlimited | Unlimited |
| Scale-out speed | 1,000 environments per function every 10 s | Tens of seconds to minutes per task | Minutes (new instances), seconds with spare capacity |
| Cold start | Yes (mitigate: SnapStart, provisioned concurrency) | Task start time | None for warm capacity |
| Memory / CPU | Up to 10 GB / 6 vCPU | Up to 120 GB / 16 vCPU | Any instance type |
| GPU | No | No | Yes |
| Concurrency model | One request per environment (except Lambda Managed Instances) | Many requests per task | Many requests per task |
| Idle cost | Zero | Per running task | Per node |
| Ops burden | Lowest | Low | Highest (patching, capacity), reduced by EKS Auto Mode / ECS Managed Instances |
Where serverless gets expensive (us-east-1 list prices):
Steady 1B requests/month, 128 MB, 100 ms:
Lambda requests 1B Γ $0.20/M = $200 + duration 12.5M GB-s Γ $0.0000166667 = $208 β ~$408
ECS 2 Γ c6g.large on-demand (~385 req/s average is easy for 2 vCPU each) β ~$99
Sustained 50K req/s (131B requests/month), 512 MB, 100 ms:
Lambda requests β $26,000 + duration β $109,500 β ~$135,000
Same load on containers is typically a small fraction of that if utilisation stays high.
Provisioned concurrency 50 Γ 1 GB for a month:
50 GB Γ 2.63M s Γ $0.0000041667 β $548 (before invocation charges), vs ~$30 for a t3.medium
The break-even depends on average utilisation: Lambda charges only for busy time, containers charge for provisioned time. A service that's busy 5% of the day favours Lambda; one at 60% sustained utilisation favours containers. Run the numbers with your traffic shape.
Combined design for this platform:
Clients β API Gateway or ALB
βββ API: ECS on Fargate/EC2, autoscaled on request count (p99 < 100 ms, no cold starts)
β or Lambda + provisioned concurrency for the bursty, low-volume endpoints
βββ async submissions β SQS
βββ workers: ECS on Spot (scale on backlog per task) or AWS Batch
βββ results β S3; completion events β EventBridge/SNS
Lambda for glue: S3 events, EventBridge rules, scheduled jobs, light transformations
- The queue decouples the API's latency from batch capacity and absorbs the 0β50K bursts.
- Scale workers on backlog per task (queue depth Γ· tasks) and
ApproximateAgeOfOldestMessage, not CPU. - The lines are blurring: Lambda Managed Instances (Lambda on EC2 you don't manage, multi-concurrency, EC2 pricing) and ECS Managed Instances / EKS Auto Mode (EC2 capacity AWS manages) let you pick the programming model and the cost model somewhat independently.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| Decision framework | Has structured criteria (utilisation, latency, duration, hardware, ops) for choosing Lambda vs containers |
| Cost awareness | Quantifies where Lambda gets expensive with correct pricing math |
| Hybrid architecture | Designs API + queue + workers with the right compute for each part |
| Provisioned concurrency | Knows what provisioned concurrency costs relative to always-on capacity |
π¬ Animated Sequence Diagram¶
π¬ Animated Serverless vs Containers Decision Framework β Lambda front-end + ECS back-end with SQS buffer β Click βΆ to play/pause. Created with Remotion.
7. Cloud-Native Design Patterns: Strangler Fig, CQRS, Saga¶
Q: "Your legacy monolith is 500K lines of code, serving 10K customers. You need to modernize without downtime. Walk through the Strangler Fig pattern for incremental migration. When would you use CQRS? How does the Saga pattern handle distributed transactions across microservices?"
What They're Really Testing: Whether you understand cloud-native patterns as practical tools for incremental modernization β not just theoretical concepts β and can sequence them for real-world migration.
Answer¶
30-second answer
Strangler fig: put a routing layer (API Gateway, ALB rules, or a proxy) in front of the monolith, then move one capability at a time behind it, with an anti-corruption layer translating between old and new models, and data synchronised (CDC or events) until the old path is gone. CQRS: separate the write model from purpose-built read models when read and write shapes or scales diverge a lot; accept eventual consistency on the read side. Saga: a sequence of local transactions with compensations instead of a distributed transaction; choreographed via events for short flows, orchestrated (Step Functions, see Q5) for long or audited ones.
Strangler fig, step by step:
Phase 1 Client β Router βββββββββββββββββββββββββββββββΊ Monolith (everything)
Phase 2 Client β Router β /inventory/* ββΊ Inventory svc (new feature, own DynamoDB)
β everything else ββΊ Monolith
Phase 3 Client β Router β /orders/* ββΊ Order svc ββ CDC/events β Monolith DB (sync both ways during transition)
β /inventory/* ββΊ Inventory svc
β rest ββΊ Monolith
Phase 4 Monolith handles nothing; zero traffic for N weeks; archive and delete
Strangler fig: the router sends migrated capabilities to new services and everything else to the monolith.
flowchart LR
C[Client] --> RT{Router}
RT -->|"/inventory/*"| INV[Inventory service]
RT -->|"/orders/*"| ORD[Order service]
RT -->|"everything else"| M[Monolith]
M <-->|"CDC or events"| ORD
- Route by path, header, tenant or percentage (canary per capability), so you can move a few tenants first and roll back by flipping the route.
- The hard part is data: during transition both systems may need the same data. Pick one owner per entity at each phase, replicate with DMS/Debezium CDC or domain events, and avoid dual writes from application code.
- Expect the long tail: reports, batch jobs and integrations that hit the monolith's database directly. Inventory them early.
CQRS:
Commands: POST /orders βββΊ Order service βββΊ DynamoDB (write model, single-item writes)
β DynamoDB Streams / outbox
βΌ
Queries: GET /orders/search, /dashboards βββ OpenSearch (search), ElastiCache (hot views),
S3 + Athena (analytics) β each a projection
CQRS: commands hit the write model, a stream feeds read-optimised projections that queries use.
flowchart LR
CMD[Commands] --> W[Order service]
W --> DDB[("DynamoDB write model")]
DDB -->|"Streams or outbox"| P[Projector]
P --> OS[(OpenSearch)]
P --> EC[(ElastiCache)]
P --> S3[("S3 + Athena")]
Q[Queries] --> OS
Q --> EC
Q --> S3
| Use CQRS when | Avoid it when |
|---|---|
| Reads need shapes the write model can't serve efficiently (search, aggregates) | Simple CRUD |
| Read and write volumes differ by orders of magnitude | Users must always read their own writes from the read model |
| Several consumers need different views | A small team can't operate the extra pipeline |
Propagation is usually sub-second but unbounded under load or failure; show "pending" states, read-your-writes from the write model where it matters, and make projections rebuildable from the source (event log or table export).
Saga by choreography:
Order svc ββOrderCreatedβββΊ Payment svc ββPaymentAuthorizedβββΊ Inventory svc ββInventoryReservedβββΊ Shipping svc
β² β β
βββββ PaymentFailed βββββββββ β
β² β
βββββ OrderCancelled βββ Payment svc refunds βββ InventoryFailedβ
| Choreography | Orchestration (Step Functions) | |
|---|---|---|
| Coupling | Services know event types, not each other | Orchestrator knows every step |
| Visibility | Reconstruct from traces and events | Execution history shows the whole flow |
| Change | Easy to add listeners; hard to change the flow | Change in one place |
| Best for | 2β4 steps, independent teams | Many steps, branching, timeouts, human approval, audit |
Either way: idempotent participants, compensations that can't be skipped, a timeout for "stuck" sagas, and a semantic lock (e.g. PENDING order status) so other operations don't act on half-finished state.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| Strangler Fig | Plans incremental migration with routing, anti-corruption layer and a data ownership plan |
| CQRS | Separates read/write paths, uses streams for sync, knows when NOT to use it |
| Saga | Compares choreography and orchestration, with idempotency, compensations and timeouts |
π¬ Animated Sequence Diagram¶
π¬ Animated Strangler Fig Pattern β incremental monolith migration with API Gateway routing and anti-corruption layer β Click βΆ to play/pause. Created with Remotion.
8. Resilience Engineering & Chaos Engineering¶
Q: "Design a resilience strategy for a payment processing system processing $1M/hour. How do you implement circuit breakers, bulkheads, and retry with exponential backoff? How do you use Chaos Engineering to validate resilience? Walk through a Game Day scenario."
What They're Really Testing: Whether you understand resilience as an engineering discipline β not just HA configuration β and can design failure injection experiments to validate system behavior under real failure conditions.
Answer¶
30-second answer
Contain failures so they degrade one feature, not the system: timeouts on every call, retries with capped exponential backoff and full jitter plus a retry budget, idempotency keys so a retried charge never double-charges, circuit breakers to fail fast when a dependency is down, bulkheads (separate pools, queues, cells) so one dependency can't exhaust shared resources, and load shedding to protect the core path. Validate with AWS Fault Injection Service (FIS) experiments that have explicit hypotheses and CloudWatch-alarm stop conditions, first in staging then in production at small blast radius, and run game days that exercise people and runbooks, not just software.
Patterns:
| Pattern | What it prevents | Key settings |
|---|---|---|
| Timeout | Threads stuck forever on a slow dependency | Below the caller's timeout; budget across hops |
| Retry with backoff + jitter | Synchronised retry storms | Cap attempts (2β3), cap delay, full jitter, retry only idempotent or idempotency-keyed operations |
| Retry budget / token bucket | Retries amplifying an outage | e.g. retries β€ 10% of requests (AWS SDKs' adaptive/standard retry modes do this) |
| Circuit breaker | Hammering a failed dependency; slow failures | Open on error rate or slow-call rate over a window, half-open probes |
| Bulkhead | One dependency consuming all threads/connections | Separate pools or separate queues/workers per dependency |
| Load shedding / admission control | Collapse under overload | Reject early with 429/503, prioritise payments over reports |
| Cell-based architecture | Region-wide blast radius | Independent cells (stacks) each serving a subset of customers |
Retry with idempotency (payment calls):
import random
import time
class TransientError(Exception): ...
def call_with_retries(op, *, idempotency_key, attempts=3, base=0.2, cap=2.0):
for attempt in range(attempts):
try:
return op(idempotency_key=idempotency_key) # gateway dedups on this key
except TransientError:
if attempt == attempts - 1:
raise
time.sleep(random.uniform(0, min(cap, base * 2 ** attempt))) # full jitter
Without the idempotency key, a timeout after the gateway charged the card plus a retry is a double charge, which is the most expensive bug in this system.
Circuit breaker behaviour:
CLOSED ββ(error rate > 50% over 20 calls, or slow calls > threshold)βββΊ OPEN
OPEN ββ(after 30 s)βββΊ HALF_OPEN ββ(probe calls succeed)βββΊ CLOSED
βββ(probe fails)βββββββββΊ OPEN
While open, the payment API returns "pending" and enqueues the charge to SQS for a worker to retry later, rather than failing the checkout. Use a library (resilience4j, Polly, or a service-mesh/proxy policy) rather than hand-rolling state machines.
Chaos engineering with FIS:
Experiment: payment-gateway-degradation
Hypothesis: >99% of checkouts complete or are queued; p99 < 2 s; no double charges
Targets: payment-service ECS tasks in one AZ (25%)
Actions:
- aws:ecs:task-network-latency # +500 ms to the gateway's port
- aws:ecs:task-network-blackhole-port # then drop traffic to it entirely
- aws:ecs:stop-task # kill 25% of tasks
Stop conditions: # CloudWatch alarms; FIS halts the experiment
- CheckoutErrorRate > 2% for 1 minute
- PaymentDLQDepth > 0
Rollback: actions end and faults are removed; your system must recover on its own
FIS (renamed from Fault Injection Simulator to Fault Injection Service in 2023) also provides scenarios such as AZ power interruption and cross-Region connectivity disruption, and integrates with ARC zonal shift so you can practise moving traffic away from an impaired AZ.
Game day: payment gateway outage:
| Time | Expected | Check |
|---|---|---|
| Tβ1 week | Hypothesis, blast radius, abort criteria, comms plan agreed | Runbooks reviewed |
| T+0 | FIS blackholes gateway traffic for 25% of tasks | β |
| T+1 min | Breaker opens; checkouts return "pending"; charges queued | Alarm fires, on-call paged, dashboard shows breaker state |
| T+5 min | Fault removed; breaker half-opens and closes | Queue drains via autoscaling on backlog |
| T+15 min | Error rate and queue age back to baseline | Reconcile: every queued charge processed exactly once |
| After | Review: what surprised us, action items with owners | Track to completion |
Typical findings: alarms on averages that hid the problem, retries in two layers multiplying load, a runbook step that no longer matches the console, autoscaling too slow to drain backlog.
Resilience metrics: availability per SLO (successful checkouts / attempts), p99 latency, queue age and DLQ depth, breaker open time, MTTD/MTTR, and error-budget burn rate alerts rather than static thresholds.
π Staff-Level Evaluation¶
| Criterion | What I'm Looking For |
|---|---|
| Circuit breaker | Implements with rate-based thresholds, half-open probes, fail-fast with a fallback |
| Retries and idempotency | Uses capped backoff with jitter and idempotency keys for payments |
| Chaos Engineering | Designs FIS experiments with hypotheses and alarm-based stop conditions |
| Post-incident culture | Runs game days and reviews with concrete action items and ownership |
π¬ Animated Sequence Diagram¶
π¬ Animated Resilience & Chaos Engineering β circuit breaker, bulkhead, retry backoff, and FIS Game Day scenario β Click βΆ to play/pause. Created with Remotion.
All 8 questions cover the full breadth of AWS architecture β from Well-Architected reviews and multi-region DR to cloud-native patterns and chaos engineering.