Well-architected AWS for LLM, RAG & agentic AI

A practical, pastel walkthrough of building a production GenAI platform on AWS — the data flow left to right, the AWS service for each box, the six Well-Architected pillars applied at every stage, and the problems that actually bite plus how to solve them. Everything is clickable and collapsible.

1The reference architecture, drawn

The whole GenAI platform on one canvas, in the zoned left-to-right style: a request enters at the client, passes guardrails, and flows through ingestion, the knowledge/vector layer, the model, and (for agents) AgentCore — all sitting on a shared security foundation. Click any box for what it is, the AWS service, and a jump straight to the matching pipeline stage and pillar detail below.

Well-Architected AWS Secure Reference Architecture — LLM + RAG + Agentic AI 1 · IDENTITIES & ACCESS IAM Identity Center MFA / FIDO2 IAM roles & policies Permission boundaries Service Control Policies Users (web / internal) 2 · SECURE NETWORKING (Zero Trust VPC) ◉ spans Availability Zones A + B AZ-a ▲ AZ-b ▼ (mirrored) PUBLIC SUBNETS AWS WAF CloudFront Application Load Balancer Edge tier only (public) PRIVATE SUBNETS (APPLICATION) ECS / EKS / Lambda Orchestrator / API layer Runs your RAG + agent code PRIVATE SUBNETS (DATA) Amazon RDS (operational) ElastiCache (Redis) Most isolated tier VPC endpoints NAT Gateway Transit Gateway PrivateLink 3 · OBSERVABILITY & SEC OPS CloudWatch CloudTrail GuardDuty Security Hub Detective Config X-Ray OpenSearch (SIEM) 4 · AI / DATA PLATFORM LAYER DATA SOURCES Amazon S3 Databases Enterprise apps APIs / web INGESTION & PREP AWS Glue Step Functions Kinesis Chunk & split RAG PIPELINE Bedrock embeddings Vector store Text splitter OpenSearch SL Retrieval: semantic + hybrid + re-rank or Bedrock Managed Knowledge Base LLM LAYER (Bedrock) Claude/Llama/Titan Converse API Model invocation Guardrails AGENTIC Orch. Mem. Plan Core TOOLS / ACTIONS APIs & microservices Databases / RDS Lambda functions Step Functions / search 5 · DATA PROTECTION & GOVERNANCE Lake Formation Glue Catalog Amazon Macie Encryption + KMS Amazon Q Business 6 · CI/CD & DEVSECOPS Code Build Scan Test Artifact Deploy Monitor INFRA AS CODE CDK / CloudFormation Terraform
Click any service box or the foundation band for detail and a jump into the text.
How to read it. Left to right is the request's journey; the foundation band underneath is what every zone depends on (identity, encryption, network isolation, detection). The seven upper zones map one-to-one onto the seven pipeline stages in section 2 — this diagram is the picture, section 2 is the walk-through, and section 3 pillars apply at every box.
Attack graph — the path an adversary walks (left to right)

The red column of the diagram as a flow. Click any stage to see what happens, a real example, and where in this architecture it gets stopped. The goal of the whole design is to break this chain at as many stages as possible.

1Reconnaissance
2Initial access
3Privilege escalation
4Lateral movement
5Data access
6Impact
Potential attack paths — per control, with real examples & safeguards

The red column of the diagram, made specific. For each control in the architecture, here is how an adversary actually defeats it, a real-world example, and how to safeguard it.

Bypassing SSO / MFA
Attack pathThe strong ones don't "crack" MFA — they sidestep the login. Adversary-in-the-Middle (AiTM): a reverse-proxy phishing kit (Evilginx, Tycoon 2FA, Mamba 2FA) sits between the user and the real Microsoft/Google page; the victim sees the genuine login, enters their real password and approves the real prompt, and the proxy steals the resulting session token — no password or code needed afterward. MFA fatigue: with the password already stolen, flood the phone with push prompts until one is approved. Help-desk / SIM-swap: socially engineer an MFA reset or port the number to capture SMS codes. Token theft: infostealer malware lifts session cookies straight from the browser.
Real worldUber (2022): an attacker with a contractor's password sent repeated MFA pushes for over an hour until one was approved, reaching internal systems, Slack and source repos. Scattered Spider (CISA AA23-320A) blended SIM-swaps, fatigue and help-desk impersonation to breach enterprises. Microsoft tracked AiTM campaigns hitting 10,000+ organizations by stealing session cookies.
SafeguardPhishing-resistant MFA — FIDO2 / passkeys — is the only method that defeats AiTM, because the key does a cryptographic handshake bound to the real domain and won't authenticate against a proxy (Google: zero successful phishing of 85,000+ staff after mandating hardware keys). Add: number-matching on any remaining push MFA, drop SMS entirely, Conditional Access on device/location, short session lifetimes with re-auth for sensitive actions, continuous access evaluation, and detection of session-token reuse from a new IP/device. Harden the help-desk identity-recovery workflow — it's now a primary target.
Privilege escalation (IAM)
Attack pathOnce inside as any principal, find an over-permissive role or a misconfiguration — a wildcard iam:PassRole, a role assumable too broadly, a policy with * actions — and pivot to admin.
Real worldThe recurring theme in cloud breaches: an initial foothold with modest rights finds a path to a powerful role because least privilege was aspirational, not enforced.
SafeguardPermission boundaries to cap maximum privilege, SCPs as org-wide guardrails, no wildcard actions on sensitive services, IAM Access Analyzer to find unintended access, and CloudTrail alerting on role-assumption anomalies. This is the Identities rail of the diagram doing its job.
Reaching the data tier / exfiltration
Attack pathFrom a compromised app node, move laterally toward the data subnet; if segmentation is weak or an S3 bucket is public, read or copy the data out.
Real worldCountless breaches trace to a single public S3 bucket or a flat network that let one foothold reach the database.
SafeguardThe diagram's private-subnet design: data tier with no internet path, security-group micro-segmentation, S3 Block Public Access on by default, KMS encryption so stolen data is useless, VPC endpoints so traffic never touches the public internet, and GuardDuty to flag exfiltration patterns.
Prompt injection → agent action (the GenAI-specific path)
Attack pathHide an instruction in a document the RAG pipeline will retrieve, or in user input. When it reaches the model, the model obeys it; if the model is an agent with tools, that injected instruction becomes a real-world action — collapsing "initial access" and "privilege escalation" into a single move.
Real worldIndirect prompt-injection research has repeatedly shown documents and web pages steering assistants into leaking data or calling tools the user never intended — the reason AWS ships Guardrails and scopes AgentCore tools.
SafeguardBedrock Guardrails on input and output; screen retrieved chunks, not just user text; a canary token in the system prompt that must never appear in output; least-privilege scoping on every agent tool; and human-in-the-loop confirmation for any irreversible action.
Backups, recovery & the metrics that prove they work

The Recover function of the diagram, made concrete. A backup that has never been restore-tested is a hope, not a control — so this is the how-to and the numbers to hold yourself to.

The two metrics everything hangs on

RPO (Recovery Point Objective) — the most data you can afford to lose, in time. RPO of 15 minutes means your backup/replication must capture changes at least every 15 minutes; anything written after the last capture is gone. RTO (Recovery Time Objective) — the longest you can be down before the impact is unacceptable. Both are business decisions, set by a Business Impact Analysis, and they dictate your backup cadence and architecture — not the other way around.

Tier your workloads — one target for everything is the classic mistake

TierTypical RPO / RTOAWS mechanism
Mission-critical DBRPO ~seconds–5 min / RTO ~1 hrRDS/Aurora point-in-time recovery (continuous), Multi-AZ, cross-region replica
Vector store & app dataRPO ~1 hr / RTO ~1–4 hrAWS Backup scheduled snapshots; re-index from source if needed
Stateless computeRPO ~24 hr / RTO ~1 hrGolden AMIs, IaC redeploy (no data to lose)
Object storage / corpusRPO ~24 hr / RTO hoursS3 versioning + cross-region replication + Object Lock

The architecture rule: 3-2-1-1-0

The modern, ransomware-aware backup rule: 3 copies of data, on 2 media types, with 1 off-site (cross-region/cross-account), 1 immutable/offline copy, and 0 errors on restore verification. On AWS: AWS Backup for policy-driven coverage across RDS, EBS, DynamoDB and S3; a separate account with immutable, encrypted vaults (S3 Object Lock) so compromised admin credentials can't delete your last line of defense.

Metrics to track — and honest targets

MetricTarget
Backup success rate≥ 99% of scheduled jobs; every failure alerted, not silently retried
Restore-test cadenceAt least quarterly (AWS Well-Architected REL09-BP04), automated where possible
Measured RTO vs. targetFull-fidelity restore + config + app verification — not just "snapshot completed"
Measured RPO vs. targetActual data-loss window from a real restore, per tier
Backup coverage% of production resources actually in a backup plan (audit across accounts)
Restore granularityCan you restore a single table/file, not just a full instance?
The trap to avoid. Jobs that report "successful" for months, then fail a real restore because the schema didn't match or nobody had a single-record runbook. AWS Backup restore testing (automated restores validated against your stated RTO) turns "we hope it works" into "we know it does." Reality check from 2026 surveys: 60% of teams say a full restore takes 6+ hours, and only 5% can do it in under an hour — measure yours before an incident does.
Detect & protect — controls by NIST function

The blue column of the reference diagram, organized Prevent / Detect / Respond / Recover.

FunctionControls
PreventWAF, Shield, IAM least privilege, MFA, SCPs, Guardrails
DetectGuardDuty, CloudTrail, Security Hub, VPC flow logs, CloudWatch alarms
RespondSSM automation, playbooks, containment, forensics
RecoverBackups, Multi-AZ, cross-region restore, IaC re-deploy
Trusted by design. The key principle from the diagram: don't just find issues — prove attackers (or agents) cannot reach what matters. Security, reliability, and privacy built in at every layer, then verified: identify assets, reduce attack surface, verify the controls actually work, monitor continuously, improve.

2The original diagram — zoomable & clickable

Your reference architecture at full resolution. Scroll or use +/− to zoom, drag to pan, and click any region to read what it is and jump to the matching section. Double-click to reset.

Well-Architected AWS Secure Reference Architecture for LLM, RAG and Agentic AI — original reference diagram, full resolution Identities & Access Secure networking (VPC) Public subnets Private subnets (application) Private subnets (data) Observability & security ops Potential attack paths Data sources Ingestion & preparation RAG pipeline Vector store LLM layer (Bedrock) Agentic AI layer Tools / actions Data protection & governance CI/CD & DevSecOps Infrastructure as Code Well-Architected overlay Key principle Detect & protect
Zoom: scroll · Pan: drag · Click a region for detail
Two ways to read it. The rest of this page is split to match how you actually build: Part 1 is the AWS foundation with no AI in it yet — the secure landing zone any workload needs. Part 2 adds the AI: the LLM, RAG, and agentic layer that sits inside that foundation. The diagram’s outer frame is Part 1; its AI/Data Platform layer is Part 2.

3Part 1 — the AWS foundation (no AI yet)

Before a single model is called, you need a secure, reliable place to run. This is the part of the diagram that would exist for any serious workload — the outer frame: identity, network, compute, data, observability, governance, and delivery. Get this right and the AI layer in Part 2 has somewhere safe to live.

Identities & access — who is allowed in

Everything starts with identity. IAM Identity Center (SSO) with MFA for people, scoped IAM roles for services, permission boundaries to cap maximum privilege, and Service Control Policies as org-wide guardrails. This is the root of least privilege — every later control (which data a query can retrieve, which tool an agent can call) inherits from here. Click the identity boxes in the section-1 diagram for each piece.

Secure networking — the Zero-Trust VPC

A VPC split into tiers you can see in the diagram: public subnets hold only edge components (WAF, CloudFront, the load balancer); private application subnets run your orchestration (ECS/EKS/Lambda) with no inbound internet; private data subnets are the most isolated, holding RDS and ElastiCache. Traffic reaches AWS services privately via VPC endpoints and PrivateLink, never the public internet. The principle: nothing sensitive is reachable from outside, and every hop is authorized.

Gateways & connectivity — NAT, Internet, endpoints, PrivateLink, Transit (with examples)

"How does something in a private subnet reach the outside \u2014 and how does the outside reach in?" There are several doors, each for a different direction and destination. Getting this wrong is the most common source of both security holes and surprise bills. Here's each one, what it's for, and when to use it.

GatewayWhat it doesWhen to use it
Internet Gateway (IGW)Two-way door to the public internet for public subnets. Both inbound and outbound. Free (you pay only data transfer).Only your edge tier (ALB, CloudFront origin, bastion) sits behind it. Never put app or data resources in a subnet routed to an IGW.
NAT Gateway (public)One-way outbound-only door for private subnets \u2014 they reach the internet, but nothing can initiate a connection back in. Managed, ~$0.045/hr + ~$0.045/GB.When private app nodes must call the public internet (a third-party API, OS package updates) but must stay unreachable from it.
NAT Gateway (private)Same one-way NAT but within AWS \u2014 no internet, no Elastic IP. Routes to other VPCs / on-prem via Transit Gateway.Overlapping CIDRs or hybrid/VPC-to-VPC traffic that must never touch the public internet.
Egress-only Internet GatewayThe NAT-equivalent for IPv6 outbound-only traffic (NAT Gateway doesn't natively do IPv6 egress).IPv6 instances that need outbound internet but no inbound.
Gateway VPC EndpointA private route to S3 and DynamoDB only, via the route table. Free. Traffic never leaves AWS.Always \u2014 deploy these first. Your RAG corpus lives in S3, so this keeps that traffic off the NAT Gateway (and off your bill).
Interface VPC Endpoint (PrivateLink)A private ENI in your subnet for most other AWS services (Bedrock, ECR, CloudWatch, KMS, Secrets Manager) and third-party SaaS. ~$0.01/hr/AZ + ~$0.01/GB.To call Bedrock, pull container images, or reach a SaaS without going over the internet. Cheaper than NAT for high-volume AWS-service traffic.
Transit GatewayA central hub connecting many VPCs and on-prem into one routing fabric. ~$0.05/hr/attachment + ~$0.02/GB.Once you have several VPCs (prod, staging, shared services). For 2\u20134 VPCs, plain VPC Peering is usually simpler and cheaper.

How they fit together in this architecture. Your Bedrock calls, S3 corpus reads, ECR image pulls, and Secrets Manager lookups should all go over VPC endpoints / PrivateLink \u2014 private, and they keep that traffic off the internet and off the metered NAT Gateway. A NAT Gateway exists only for the genuinely-external calls (a third-party API the agent must reach). The Internet Gateway serves only the public edge. That layering is both the security story (nothing sensitive is internet-reachable) and the cost story.

Example \u2014 the free win everyone misses. A Gateway Endpoint for S3 is free and takes one route-table entry:
aws ec2 create-vpc-endpoint --vpc-id $VPC --service-name com.amazonaws.us-east-1.s3 --route-table-ids $RTB
Without it, every byte your RAG pipeline reads from S3 is billed through the NAT Gateway at ~$0.045/GB. With it, that traffic is free and never leaves AWS. On a data-heavy platform this alone can save thousands a month \u2014 deploy Gateway Endpoints for S3 and DynamoDB first, always.
When you do NOT need a NAT Gateway at all. If your workload only talks to AWS services (via endpoints), other VPCs (via peering/Transit Gateway), or on-prem (via Direct Connect) \u2014 and never the public internet \u2014 skip the NAT Gateway entirely. That removes both a cost and an unnecessary egress path. Many GenAI backends that live entirely on Bedrock + S3 + RDS need no NAT at all.
Compute & data tiers

Compute is serverless-first (Lambda) or containerized (ECS/EKS) in the private application tier — it scales to zero and carries no standing OS to patch where possible. The data tier (RDS for operational data, ElastiCache/Redis for caching) sits in the most isolated subnet, encrypted at rest with KMS. Note that RDS here can double as your vector store via pgvector — the bridge into Part 2.

ECS vs EKS vs Lambda — which compute to run your platform on

The diagram's application box says "ECS / EKS / Lambda" because all three run your orchestration code in the private tier — but they're very different tools. All three are serverless-capable (no servers you patch), integrate with IAM/VPC/CloudWatch the same way, and can call Bedrock. The difference is how much of the plumbing you own and what shape your workload is.

 AWS LambdaAmazon ECS (Fargate)Amazon EKS
What it isFunctions — you upload code, AWS runs it per requestAWS's own container orchestrator; Fargate runs containers with no servers to manageManaged Kubernetes — the industry-standard container platform, AWS-hosted control plane
Unit of workA single function invocationA long-running container/serviceContainers (pods) on a Kubernetes cluster
Scales to zeroYes — pay only per requestWith Fargate, scale in to zero tasksNot really — the cluster/control plane runs continuously
Startup / latencyMillisecond–second; cold starts on idleSeconds; warm services have no cold startSeconds; warm pods have no cold start
Runtime limits15-min max, memory/size caps — not for long jobsNo time limit; any long-running processNo time limit; full workload control
Operational effortLowest — AWS owns almost everythingLow–medium — you define tasks/servicesHighest — you own Kubernetes config, upgrades, add-ons
Best forEvent-driven glue: an API call that embeds a query, retrieves, and calls the model; ingestion triggersSteady web/API services and orchestration that must stay warm, without Kubernetes overheadLarge teams already standardized on Kubernetes, or complex multi-service platforms needing its ecosystem

How to choose, in one line each. Lambda when the work is short, spiky, and event-driven — the default for a RAG request handler or an ingestion trigger, because it scales to zero and you write the least infrastructure. ECS on Fargate when you need a service that stays warm (no cold starts), handles long or streaming requests, or runs steadily — containers without the Kubernetes learning curve. EKS when your organization is already on Kubernetes or the platform is complex enough to need its ecosystem (service mesh, operators, portability across clouds) — powerful, but the most to operate.

For a GenAI platform specifically. A very common, cost-effective pattern: Lambda for the request path and ingestion (scales to zero between bursts), Fargate for anything that must hold a warm connection or run longer than 15 minutes (a streaming agent loop, a batch re-indexing job), and EKS only if you're already invested in Kubernetes. Don't reach for EKS just to run a chatbot — the cluster you keep running is cost and toil you may not need.
EKS vs ECS vs Lambda — what & how to secure each

The same three compute choices read through a security lens: what runs on each, what you are responsible for, the key controls to put in place, and how to detect trouble. Reading left→right is "more you manage → more AWS manages."

⎈ EKS (Kubernetes)
What runs
  • Kubernetes workloads (pods)
You manage
  • Cluster, nodes, pods
  • Networking
  • Kubernetes security
Key security controls
  • Private cluster / API
  • IAM Roles for Service Accounts (Pod Identity)
  • RBAC
  • Network Policies
  • Admission Controllers
  • Image scanning (ECR)
  • Secrets Manager
  • Runtime detection
Detect
  • CloudTrail, GuardDuty
  • Security logs, Security Hub
  • Container runtime tools
▤ ECS (Containers)
What runs
  • Containers (tasks)
You manage
  • Tasks, task roles
  • Networking
  • Container images
Key security controls
  • Private subnets
  • Security Groups
  • Task IAM Role (least privilege)
  • Image scanning (ECR)
  • Secrets Manager
  • WAF (internet-facing)
  • Runtime monitoring
Detect
  • CloudTrail, GuardDuty
  • Security Hub, CloudWatch
  • Container runtime tools
λ Lambda (Functions)
What runs
  • Functions (code)
You manage
  • Code, execution role
  • Permissions, triggers
  • Dependencies
Key security controls
  • Least-privilege IAM role
  • API auth & throttling
  • Input validation
  • Secrets Manager
  • Dependency scanning
  • Code signing (optional)
  • VPC / egress controls
Detect
  • CloudTrail, GuardDuty
  • Security Hub, CloudWatch
  • logs & metrics
Common security principle (all three). Least-privilege identity → limited network access → secure code & dependencies → secrets management → continuous detection & monitoring. The compute choice changes who patches what, but the security spine is identical.
Service briefs — what each service is & why it's needed

A one-open-at-a-time reference for the services in the diagram. Each brief says, in plain language, what the service is and why the architecture needs it.

Amazon EKS

What it is. Managed Kubernetes — AWS runs the Kubernetes control plane; you run containerized workloads (pods) on it.

Why it’s needed. You need it when your org is already standardized on Kubernetes or the platform is complex enough to want its ecosystem (service mesh, operators, portability). Powerful, but the most to operate.

Amazon ECS

What it is. AWS's own container orchestrator; with Fargate it runs your containers (tasks) with no servers to manage.

Why it’s needed. You need it for steady services and orchestration that must stay warm, without taking on Kubernetes. The pragmatic default for long-running containers.

AWS Lambda

What it is. Serverless functions — you upload code, AWS runs it per request and scales to zero.

Why it’s needed. You need it for short, event-driven work (a RAG request handler, an ingestion trigger). Least infrastructure to own; 15-minute max per invocation.

AWS WAF

What it is. A Web Application Firewall that inspects and filters HTTP(S) traffic at the edge before it reaches your app.

Why it’s needed. You need it on anything internet-facing to block common web attacks (injection, bad bots, floods) and to enforce rate limits — the first gate in front of CloudFront/ALB.

Amazon CloudFront

What it is. AWS's global content delivery network (CDN) that caches and serves content from edge locations.

Why it’s needed. You need it to absorb traffic spikes, cut latency, and give WAF a global choke point in front of your origin.

Amazon VPC

What it is. Your isolated virtual network in AWS, divided into public and private subnets you control.

Why it’s needed. You need it as the container for everything — it's how you keep app and data tiers off the public internet and enforce Zero-Trust segmentation.

Amazon RDS / Aurora

What it is. Managed relational databases (PostgreSQL, MySQL, etc.) with automated backups, patching, and Multi-AZ failover.

Why it’s needed. You need it for operational data and, via pgvector, as a low-cost vector store. Multi-AZ gives you resilience without managing a database server.

Amazon Bedrock

What it is. AWS's managed platform for generative AI — foundation models, RAG, guardrails, and agents behind one API.

Why it’s needed. You need it to call models (Claude, Titan, Llama) without hosting them, and to get RAG, Guardrails, and AgentCore as managed building blocks.

Bedrock Guardrails

What it is. A configurable safety layer that screens model input and output — content filters, PII redaction, denied topics.

Why it’s needed. You need it to block prompt injection, filter harmful content, and redact PII on both what goes in and what comes out.

Amazon ECR

What it is. A private container registry for storing and scanning your Docker images.

Why it’s needed. You need it so ECS/EKS pull trusted, vulnerability-scanned images — supply-chain hygiene for containers.

AWS KMS

What it is. Key Management Service — create and control the encryption keys that protect your data at rest.

Why it’s needed. You need it so that even if data is exfiltrated, it's unreadable; keys you own and can rotate/audit.

AWS IAM

What it is. Identity and Access Management — users, roles, and policies that decide who and what can do anything in AWS.

Why it’s needed. You need it as the foundation of least privilege; every other control assumes IAM is scoped tightly.

AWS CloudTrail

What it is. An immutable audit log of every API call made in your account.

Why it’s needed. You need it to know who did what and when — the backbone of detection, forensics, and compliance.

Amazon GuardDuty

What it is. Managed threat detection that continuously analyzes account activity for malicious or anomalous behavior.

Why it’s needed. You need it to catch exfiltration, credential misuse, and reconnaissance without building detection from scratch.

The orchestration layer — how the pieces are coordinated (with examples)

"Compute" is what runs your code; "orchestration" is how the steps are coordinated \u2014 how a request flows through retrieve → model → tool → respond, how ingestion runs, and how an agent decides its next action. Same idea as the compute choice: pick the lightest tool that fits the shape of the work.

Pattern / toolWhat it coordinatesWhen to use it
In-code (Lambda / service)The request path itself: one function embeds the query, calls Retrieve, builds the prompt, calls the model, returns. No external orchestrator \u2014 just your code.The default for a simple RAG request. Fast, cheap, nothing extra to run.
Step FunctionsA visual state machine for multi-step, long, or branching workflows \u2014 with retries, error handling, parallelism, and waits built in. Each step can be a Lambda, a container, or an AWS service call.Ingestion pipelines (parse → chunk → embed → index), batch re-indexing, or any flow with retries and branches you don't want to hand-code.
EventBridge / SQSEvent-driven decoupling \u2014 an S3 upload emits an event that triggers ingestion; a queue smooths bursts so nothing is dropped.When work should happen in reaction to something (a new document) or when you need to buffer spikes.
Bedrock AgentCoreThe agent's own reasoning loop: plan → call a tool → observe → decide next step, with memory and tool-routing managed for you. This is orchestration by the model, not by fixed code.When the sequence of steps isn't known in advance and the model must decide \u2014 the agentic layer of the diagram.
Managed Knowledge BaseCollapses the whole retrieve-augment-generate orchestration into one managed call (RetrieveAndGenerate).When you want AWS to own the RAG orchestration entirely and you're not differentiating on retrieval.

The distinction that matters. There are two kinds of orchestration here, and they answer to different owners. Deterministic orchestration \u2014 Step Functions, EventBridge, your own code \u2014 is a fixed sequence you design; use it for ingestion, batch jobs, and the plumbing of the request path. Agentic orchestration \u2014 AgentCore \u2014 is a dynamic sequence the model decides at runtime; use it only where the steps genuinely can't be predetermined, because handing control to the model is powerful but raises the security stakes (see the prompt-injection and least-privilege guidance).

Example \u2014 an ingestion pipeline as a state machine. A document lands in S3 → EventBridge fires → Step Functions runs: parse (Lambda)chunk (Lambda)embed (Bedrock)index (vector store), with automatic retries on each step and a dead-letter queue for failures. You get reliability and visibility (every run is traceable) without writing retry loops by hand.
Start simple. Most platforms begin with in-code orchestration for the request path and a Managed Knowledge Base for RAG \u2014 no Step Functions, no agents. Add Step Functions when a workflow grows multi-step and failure-prone, and add AgentCore only when the model genuinely needs to choose its own path. Reaching for an agent framework on day one is the orchestration equivalent of reaching for EKS to run a chatbot.
Observability & security operations

The right-hand column of the diagram: CloudWatch (metrics/alarms), CloudTrail (audit of every API call), GuardDuty (threat detection), Security Hub (posture), Detective, Config, X-Ray (tracing), and OpenSearch as a SIEM. This is how you know what is happening — and it is pure AWS foundation, in place before any AI runs.

Data protection, governance & delivery

Data protection (Lake Formation, Glue Data Catalog, Macie for PII discovery, KMS encryption, Amazon Q Business) governs who can touch what. CI/CD & DevSecOps (code → build → scan → test → artifact → deploy → monitor) delivers changes safely, and Infrastructure-as-Code (CDK, CloudFormation, Terraform) makes the whole foundation repeatable and reviewable. Click any of these boxes in section 1 for the specific service.

Availability Zones (Multi-AZ) — the reliability backbone

What they are. An AWS Region (say us-east-1) is made of multiple Availability Zones — physically separate data centers, each with its own power, cooling, and networking, connected by fast private links. They're close enough for low-latency replication but far enough apart that a fire, flood, or power failure in one won't take down another. In the diagram, the whole VPC and every subnet tier (public, application, data) is replicated across at least two AZs — shown by the "spans Availability Zones A + B" badge and the dashed AZ-a / AZ-b divider.

Why it matters. A single data center will eventually fail. If your database, app node, or load balancer lives in only one AZ, that failure is your outage. Spreading across AZs turns a data-center failure into a non-event — traffic and data keep flowing from the healthy zones. This is the concrete meaning of the Reliability pillar in section 5.

The practice. Create at least one subnet per tier in each of two (ideally three) AZs. Run RDS/Aurora in Multi-AZ mode so a standby in a second AZ takes over automatically. Put app instances behind a load balancer that spreads across AZs, in an Auto Scaling group that spans them. Keep AZs roughly balanced so losing one still leaves enough capacity. For the strictest workloads (RPO near zero), use synchronous replication across AZs. Click the ◉ Availability Zones badge in the section-1 diagram for the configurable Terraform.

AZ vs Region. Multi-AZ protects against a data-center failure within a region and is the default for production. Multi-Region (a copy in an entirely different region) protects against a whole-region outage and is a bigger, costlier step — reserve it for the workloads whose RTO/RPO justify it, as covered in the backups section.
The Part 1 test. If you deleted every AI box from the diagram, this is what remains — and it should still be a well-architected system. Build it first. The AI layer in Part 2 plugs into it, not around it.

4Part 2 — adding AI: LLM, RAG & agents

Now the AI/Data Platform layer that sits inside the Part-1 foundation. A request flows left to right through guardrails, retrieval, the model, and (for agents) tools. Click each stage for the AWS service, the pillars applied there, and the pitfalls.

A RAG/agentic platform is a pipeline: a user question flows through guardrails, retrieval, a model, and back. Click each stage to see the AWS service that owns it, how the Well-Architected pillars apply there specifically, and the problem that stage tends to create with its fix. This is the diagram everything else links back to.

👤
Client & API
the entry point
🛡
Guardrails
safety in/out
📄
Ingestion
docs → chunks
🧮
Embed & index
chunks → vectors
🔍
Retrieve
vector search
🧠
Model
the LLM
📊
Observe
logs & evals
Click any stage above for its AWS service, pillar guidance, and pitfalls.
The one-call shortcut vs. building it yourself. Amazon Bedrock Managed Knowledge Bases collapse the Ingestion, Embed/Index, and Retrieve stages into a managed service — you point it at S3 and it handles chunking, embedding, vector storage, and retrieval. Build the stages yourself only when retrieval is itself your product's differentiator. The stages below explain both paths so you know what the managed service is doing for you.
The agentic layer — when the model can act

An agent is an LLM that can call tools and take actions. AWS’s path is Bedrock AgentCore: a secure runtime (with a VPC-only mode), a Gateway that turns APIs and Knowledge Bases into agent tools with auto-generated role-based permissions, built-in memory, and Observability for what the agent actually did. Classic Bedrock Agents still suit low-code, KB-heavy workflows.

Security dominates here. An injected instruction that reaches a tool call becomes a real-world action. Scope every tool to least privilege, require confirmation for irreversible actions, and run guardrails on the agent’s inputs and outputs.
Reliability meets the real world. Cap steps, set per-run timeouts and budgets, and make tools idempotent so a retry can’t double-charge or double-write.
Where Part 1 and Part 2 meet. Every AI box lives inside a Part-1 subnet, uses Part-1 identity to scope what it can retrieve, encrypts with Part-1 KMS, and is watched by Part-1 observability. The AI layer is not a separate system — it is a tenant of the secure foundation.

5The Well-Architected Framework, applied to this diagram

The AWS Well-Architected Framework is six pillars — lenses you hold up to a design to check it is sound. AWS added a dedicated Generative AI Lens and a Responsible AI Lens for AI workloads. Here is what each pillar means, and exactly where it shows up in the reference architecture above.

1 · Operational excellence

Run and improve the system. In the diagram: the CI/CD band and Infrastructure-as-Code (CDK/Terraform) make everything repeatable; CloudWatch dashboards and alarms give you eyes; for AI, version prompts, models, and knowledge bases like code, and gate releases on evals. Actionable: automate ingestion and deploys, run game-days, treat a prompt change like a code deploy.

2 · Security

Protect data, systems, and identities. In the diagram: the Identities rail (least privilege, MFA, SCPs), the Zero-Trust VPC (private subnets, PrivateLink), KMS encryption, and — for AI — Bedrock Guardrails on every call plus least-privilege agent tools. Actionable: enforce least privilege, encrypt in transit and at rest, screen retrieved documents for injection, never leak the system prompt.

3 · Reliability

Recover from failure, meet demand. In the diagram: Multi-AZ RDS, the ElastiCache tier, backups and cross-region restore. For AI: handle model throttling and timeouts, multi-AZ vector store, and a graceful fallback when retrieval returns nothing (“I don’t know” beats a hallucination). Actionable: test restores, define RTO/RPO, cap agent steps.

4 · Performance efficiency

Use resources well. In the diagram: right-sized compute, edge caching via CloudFront, Redis for hot data. For AI: right-size the model to the task, cache prompts and embeddings, tune retrieval top-k, stream tokens for perceived speed. Actionable: the cheapest model that passes eval; a re-ranker beats a bigger top-k.

5 · Cost optimization

Best value, not lowest spend. In the diagram: S3 lifecycle tiering, Savings Plans, auto-stop for dev, Cost Explorer budgets. For AI this is where budgets are won: batch inference (~50% off), prompt caching (~31% off), and the right vector tier (pgvector cheap small, S3 Vectors cheap huge, OpenSearch fast). Actionable: attribute cost per feature and hunt the expensive queries.

6 · Sustainability

Minimize environmental impact. In the diagram: efficient instance types, serverless where possible, S3 lifecycle to archive. For AI: smaller models where they suffice, caching to avoid recompute, cold-tier idle vectors, schedule batch work off-peak. Actionable: measure with the AWS carbon-footprint tool and prefer the smallest sufficient model.

The key principle, restated. Don’t just find issues — prove attackers or agents cannot reach what matters (people, process, data, safety). Walk the six pillars against your own version of this diagram, box by box, and you have done a Well-Architected review.

6Choosing the vector store — the decision that shapes cost

The vector database is where RAG lives or dies on cost and latency. AWS gives you several, and the right answer depends on scale and how fast you need answers. Real tradeoffs, with the numbers people actually report.

OptionBest whenTradeoff
Aurora PostgreSQL + pgvectorUnder ~5M vectors; you already use Postgres; want relational joins with vectorsCheap at small scale; you tune the index (HNSW params) yourself
OpenSearch Serverless (k-NN)Millions of vectors; need fast hybrid search + metadata filtering at scaleFastest (~45ms), but the most expensive; OCU-based billing
S3 VectorsHuge scale, cost is the priority, latency is not critical~90% cheaper, but slow (~260ms) and cold-start latency; not a database
Bedrock Managed KBYou want none of the above to be your problemManaged end-to-end; less control over chunking/retrieval internals
The pragmatic pattern: tier your vectors. Many production systems combine them — ElastiCache for a hot semantic cache, OpenSearch for warm hybrid search, and S3 Vectors for cold persistent storage. Start with one (pgvector for a prototype, Managed KB to skip the plumbing) and only add tiers when cost or latency data tells you to. Switching embedding models means re-indexing everything — vectors from different models are not comparable.

7Practical build order

You do not build all six stages at once. This is the order that gets you to a working, well-architected system without over-engineering the prototype.

Step by step — prototype to production

1. Start managed. Bedrock + a Managed Knowledge Base pointed at an S3 bucket. Use the Converse API (model-agnostic, forward-compatible). You have a working RAG in a day, and you learn what the managed service does before you consider replacing any of it.

2. Add guardrails immediately. Bedrock Guardrails on input and output, plus a canary token in the system prompt. Do this before real users, not after an incident.

3. Measure before optimizing. Turn on model-invocation logging and evals. Get retrieval quality and cost numbers before you touch the vector store or model choice — optimize with data, not guesses.

4. Right-size on evidence. Now pick the cheapest model that passes eval, tune top-k, add prompt caching, and move the vector store to the tier your numbers justify (pgvector → OpenSearch → S3 tiers).

5. Add agency last, carefully. Only once retrieval is trustworthy do you give the model tools via AgentCore — with least-privilege scoping and confirmation on irreversible actions from the first tool, not retrofitted later.

The through-line. Managed first, guardrails early, measure before optimizing, agency last. Every step maps to a stage in the section-1 diagram and a pillar in section 2 — click back to those to see the detail for whichever step you are on.

8Glossary

Every acronym and term used on this page, defined in plain language. Type to filter.

3-2-1-1-0 rule
Ransomware-aware backup rule: 3 copies of data, on 2 media types, 1 off-site, 1 immutable/offline, and 0 errors on restore verification.
Adversary-in-the-Middle (AiTM)
A phishing attack where a reverse proxy sits between the victim and the real login page, capturing the session token after a genuine login — defeating most MFA.
AgentCore
Amazon Bedrock's production platform for building and running AI agents — secure runtime, tool Gateway, memory, and observability.
Agentic AI
An LLM that can plan, reason, and take actions by calling tools/APIs — not just answer questions.
Availability Zone (AZ)
One of several physically separate data centers within an AWS Region, each with independent power, cooling, and networking. Spreading subnets and databases across AZs — "Multi-AZ" — is how a design survives a single data-center failure. The backbone of the Reliability pillar.
Region
A geographic AWS location (e.g. us-east-1) made up of multiple Availability Zones. Multi-AZ protects within a region; Multi-Region protects against a whole-region outage.
ALB (Application Load Balancer)
AWS load balancer that routes incoming requests to your application tier.
AMI (Amazon Machine Image)
A saved template of a server's disk used to launch identical instances — a 'golden AMI' is a hardened, approved baseline.
Aurora
AWS's managed relational database (MySQL/PostgreSQL-compatible); PostgreSQL Aurora can host vectors via pgvector.
Bedrock
Amazon's managed platform for building generative-AI applications — foundation models, RAG, guardrails, and agents behind one API.
BIA (Business Impact Analysis)
The exercise that determines how much downtime and data loss each system can tolerate — the input that sets RTO and RPO.
Canary token
A secret planted in the system prompt that must never appear in output; if it does, it signals a prompt-injection/exfiltration attempt.
CDK (Cloud Development Kit)
AWS's infrastructure-as-code tool that lets you define cloud resources in a programming language (TypeScript, Python, etc.).
Chunking
Splitting source documents into smaller passages so retrieval can return precise, relevant pieces to the model.
CloudFront
AWS's content delivery network (CDN) — caches content at the edge and absorbs traffic spikes.
CloudTrail
AWS's audit log of every API call in an account — who did what, when.
CloudWatch
AWS's monitoring service — metrics, logs, dashboards, and alarms.
Cognito
AWS's service for user sign-up, sign-in, and identity (authentication) at the application edge.
Conditional Access
Identity policy that allows or blocks a login based on context — device, location, risk score — rather than just the password and code.
Converse API
Bedrock's recommended, model-agnostic interface for chat-style calls — swap models without rewriting.
DevSecOps
Building security into the software delivery pipeline (CI/CD) rather than bolting it on afterward.
ECS / EKS
AWS container services — Elastic Container Service and Elastic Kubernetes Service — for running your orchestration code.
ElastiCache
AWS's managed in-memory cache (Redis/Valkey) — used for fast repeated answers and semantic caching.
Embedding
A list of numbers (a vector) that captures the meaning of a chunk of text, so similar meanings sit close together.
FIDO2 / passkey
Phishing-resistant authentication that does a cryptographic handshake bound to the real website's domain — it won't authenticate against a proxy, so it defeats AiTM.
Foundation model
A large, general-purpose model (Claude, Llama, Titan) accessed via API, used as the basis for generation.
GuardDuty
AWS's account-wide threat-detection service — flags anomalous or malicious activity.
Guardrails
Bedrock's safety layer that screens model input and output — content filtering, PII redaction, injection defense.
HNSW
Hierarchical Navigable Small World — the approximate-nearest-neighbor index algorithm most vector stores use to search vectors fast.
Hybrid search
Combining vector (semantic) search with keyword search to improve retrieval recall — catches both meaning and exact terms.
IaC (Infrastructure as Code)
Defining cloud infrastructure in version-controlled files (CDK, CloudFormation, Terraform) so it's repeatable and reviewable.
IAM (Identity and Access Management)
AWS's system of users, roles, and policies that controls who can do what — the foundation of least privilege.
IAM Identity Center
AWS's single-sign-on (SSO) service for workforce access across accounts.
KMS (Key Management Service)
AWS's service for creating and controlling encryption keys — encrypt data at rest with keys you own.
Knowledge Base
Bedrock's managed RAG service — point it at S3 and it handles chunking, embedding, vector storage, and retrieval.
Lake Formation
AWS's service for fine-grained governance and access control over data lakes.
Lambda
AWS's serverless compute — runs code on demand with no server to manage; scales to zero.
Least privilege
Granting each identity or tool exactly the permissions it needs and no more — the core security principle.
LLM (Large Language Model)
A model trained on vast text that generates language — answers, summaries, code — accessed here via Bedrock.
Macie
AWS's service that discovers and classifies sensitive data (like PII) in S3 automatically.
MFA (Multi-Factor Authentication)
Requiring a second factor beyond a password. Note: MFA protects the login moment, not the session that follows.
MFA fatigue
An attack that floods a user with push prompts (after stealing the password) until they approve one out of frustration.
Multi-AZ
Running across multiple Availability Zones (isolated datacenters) in a region for resilience against a single-zone failure.
NAT Gateway
Gives private-subnet resources controlled outbound-only internet access.
OpenSearch Serverless
AWS's managed search/vector engine — fast hybrid and k-NN vector search at scale; also used as a SIEM.
pgvector
A PostgreSQL extension that stores and searches vectors — the cheap option for smaller knowledge bases.
PII (Personally Identifiable Information)
Data that identifies a person — must be discovered, protected, and often redacted.
PITR (Point-in-Time Recovery)
Restoring a database to its exact state at a chosen second — gives a very low RPO (RDS/Aurora, DynamoDB).
PrivateLink
Private connectivity to AWS and SaaS services that keeps traffic off the public internet.
Prompt injection
An attack that hides instructions in user input or retrieved documents to make the model do something unintended — worse for agents, where it becomes an action.
RAG (Retrieval-Augmented Generation)
Grounding an LLM's answer in retrieved documents so it uses current, private, or domain-specific facts instead of only its training data.
RDS (Relational Database Service)
AWS's managed relational databases (PostgreSQL, MySQL, etc.).
Re-ranking
A second step that reorders retrieved chunks by relevance before sending the best to the model.
REL09-BP04
The AWS Well-Architected Reliability best practice that says: periodically restore backups to verify they actually work and meet your RTO/RPO.
RPO (Recovery Point Objective)
The maximum data loss you can tolerate, measured in time — it sets how often you must back up or replicate.
RTO (Recovery Time Objective)
The maximum downtime you can tolerate before impact is unacceptable — it sets how fast you must be able to restore or fail over.
S3 (Simple Storage Service)
AWS's object storage — the usual home for the document corpus a RAG system retrieves from.
S3 Vectors
Native vector storage in S3 — the cheapest option at huge scale, but slower; not a full database.
SBOM (Software Bill of Materials)
A list of every component in a piece of software — used to track and respond to vulnerabilities.
SCP (Service Control Policy)
An AWS Organizations guardrail that limits what accounts are allowed to do at all, regardless of IAM.
Security Hub
AWS's service that aggregates security findings and posture across the account.
Session token
The credential your browser holds after login that keeps you signed in — stealing it (via AiTM or malware) bypasses MFA entirely.
SIEM
Security Information and Event Management — central collection and analysis of security logs (here, OpenSearch).
SIM swap
Tricking a mobile carrier into moving a victim's number to the attacker's SIM, so SMS one-time codes go to the attacker.
SSO (Single Sign-On)
One authenticated identity used across many applications — convenient, but a high-value target.
Step Functions
AWS's service for orchestrating multi-step workflows reliably, with retries.
Terraform
A popular multi-cloud infrastructure-as-code tool.
Titan
Amazon's own family of foundation and embedding models on Bedrock.
Token theft
Stealing a valid session token (often via infostealer malware) to hijack a signed-in session without needing the password or MFA.
TOTP
Time-based One-Time Password — the 6-digit authenticator-app code; better than SMS but still phishable via AiTM.
Vector / vector store
A vector is the numeric representation of meaning; a vector store (pgvector, OpenSearch, S3 Vectors) holds them for similarity search.
VPC (Virtual Private Cloud)
Your isolated private network in AWS, divided into subnets you control.
VPC endpoint
A private door from your VPC to an AWS service, so traffic never traverses the public internet.
WAF (Web Application Firewall)
Filters and blocks malicious web traffic at the edge before it reaches your app. (Not to be confused with the Well-Architected Framework.)
Well-Architected Framework
AWS's six pillars — operational excellence, security, reliability, performance efficiency, cost optimization, sustainability — for reviewing a design; with dedicated Generative AI and Responsible AI lenses.
Zero Trust
A security model that trusts nothing by default — every request is authenticated and authorized, even inside the network.

9Implementation checklist — build it line by line

The reference architecture as an ordered, do-this-then-that checklist. Work top to bottom: each phase depends on the one before it. Tick items off as you go — your progress updates live. (Progress is per session; it resets if you reload.)

0 of 47 done (0%)
The one rule. Do the phases in order. Identity and network guardrails (Phases 0–1) must exist before any data, compute, or model lands on top of them — that ordering is what makes the result well-architected rather than bolted-on.
Cost at a glance. Every step below carries a cost tag: Free (no AWS charge), $ (small / usage-based), $$ (a real line item), $$$ (typically among your largest). The pattern: the guardrails and structure are mostly free — Organizations, IAM, SCPs, VPC, subnets, gateways-that-matter, Well-Architected review — while the metered costs are the things that run and process data: NAT, RDS Multi-AZ, and above all Bedrock tokens, which usually dominate. Figures are 2026 us-east-1 list rates, region-dependent and subject to change — verify on the AWS pricing pages before budgeting.
Phase 0 — Landing zone & identity (before anything runs)
Example — Terraform
Terraform — an org account (AWS Organizations)
resource "aws_organizations_account" "prod" {
  name      = "workload-prod"
  email     = "aws-prod@example.com"
  parent_id = aws_organizations_organizational_unit.workloads.id
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — SCP denying public S3 + CloudTrail-off
resource "aws_organizations_policy" "guardrails" {
  name = "baseline-guardrails"
  type = "SERVICE_CONTROL_POLICY"
  content = jsonencode({
    Version = "2012-10-17"
    Statement = [
      { Sid = "DenyCloudTrailStop", Effect = "Deny",
        Action = ["cloudtrail:StopLogging","cloudtrail:DeleteTrail"], Resource = "*" },
      { Sid = "DenyPublicS3", Effect = "Deny",
        Action = "s3:PutBucketPublicAccessBlock", Resource = "*",
        Condition = { StringNotEquals = { "s3:PublicAccessBlockConfiguration.BlockPublicAcls" = "true" } } }
    ]
  })
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — IAM Identity Center MFA enforcement
# In IAM Identity Center settings, set MFA to "always-on" and
# authenticator type to security keys / passkeys (WebAuthn).
resource "aws_ssoadmin_permission_set" "admin" {
  name             = "AdminAccess"
  instance_arn     = tolist(data.aws_ssoadmin_instances.this.arns)[0]
  session_duration = "PT1H"   # short sessions
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — role with a permission boundary
resource "aws_iam_role" "app" {
  name                 = "rag-app-role"
  permissions_boundary = aws_iam_policy.boundary.arn
  assume_role_policy   = data.aws_iam_policy_document.assume.json
}
resource "aws_iam_policy" "boundary" {
  name   = "app-boundary"
  policy = data.aws_iam_policy_document.boundary.json  # caps max privilege
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — org-wide CloudTrail to a central bucket
resource "aws_cloudtrail" "org" {
  name                          = "org-trail"
  s3_bucket_name                = aws_s3_bucket.log_archive.id
  is_organization_trail         = true
  is_multi_region_trail         = true
  enable_log_file_validation    = true
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — CLI
CLI — enable GuardDuty + Security Hub
aws guardduty create-detector --enable
aws securityhub enable-security-hub \
  --enable-default-standards
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 1 — Network foundation (the Zero-Trust VPC)
Example — Terraform
Terraform — VPC across two AZs
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
}
# subnets created per-AZ below (step 8)
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — three subnet tiers in two AZs
locals { azs = ["us-east-1a","us-east-1b"] }

resource "aws_subnet" "public" {
  for_each          = toset(local.azs)
  vpc_id            = aws_vpc.main.id
  availability_zone = each.value
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, index(local.azs, each.value))
}
resource "aws_subnet" "app"  { for_each = toset(local.azs)  /* private, +10 offset */
  vpc_id = aws_vpc.main.id  availability_zone = each.value
  cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 10 + index(local.azs, each.value)) }
resource "aws_subnet" "data" { for_each = toset(local.azs)  /* private, +20 offset */
  vpc_id = aws_vpc.main.id  availability_zone = each.value
  cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 20 + index(local.azs, each.value)) }
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — Internet Gateway (public route)
resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.main.id }
resource "aws_route" "public_inet" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — free S3 Gateway Endpoint (do first)
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [aws_route_table.app.id, aws_route_table.data.id]
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — Interface Endpoint (PrivateLink) for Bedrock
resource "aws_vpc_endpoint" "bedrock" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.us-east-1.bedrock-runtime"
  vpc_endpoint_type   = "Interface"
  private_dns_enabled = true
  subnet_ids          = [for s in aws_subnet.app : s.id]
  security_group_ids  = [aws_security_group.endpoints.id]
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — NAT Gateway (only if internet egress needed)
resource "aws_eip" "nat" { domain = "vpc" }
resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public["us-east-1a"].id
}
# Skip this whole resource if all egress is via VPC endpoints.
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — default-deny security group, allow one flow
resource "aws_security_group" "app" {
  vpc_id = aws_vpc.main.id
  # no ingress rules = default deny
  egress { from_port = 443 to_port = 443 protocol = "tcp"
           cidr_blocks = ["0.0.0.0/0"] }   # tighten to endpoint SGs in prod
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — WAF WebACL on the ALB/CloudFront
resource "aws_wafv2_web_acl" "edge" {
  name  = "edge-acl"
  scope = "REGIONAL"
  default_action { allow {} }
  rule {
    name     = "AWSManagedCommon"
    priority = 1
    override_action { none {} }
    statement { managed_rule_group_statement {
      name = "AWSManagedRulesCommonRuleSet"  vendor_name = "AWS" } }
    visibility_config { cloudwatch_metrics_enabled = true
      metric_name = "common"  sampled_requests_enabled = true }
  }
  visibility_config { cloudwatch_metrics_enabled = true
    metric_name = "edge"  sampled_requests_enabled = true }
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 2 — Data foundation & backups
Example — Terraform
Terraform — private, versioned, encrypted S3 bucket
resource "aws_s3_bucket" "corpus" { bucket = "rag-corpus-prod" }
resource "aws_s3_bucket_public_access_block" "corpus" {
  bucket = aws_s3_bucket.corpus.id
  block_public_acls = true  block_public_policy = true
  ignore_public_acls = true  restrict_public_buckets = true
}
resource "aws_s3_bucket_versioning" "corpus" {
  bucket = aws_s3_bucket.corpus.id
  versioning_configuration { status = "Enabled" } }
resource "aws_s3_bucket_server_side_encryption_configuration" "corpus" {
  bucket = aws_s3_bucket.corpus.id
  rule { apply_server_side_encryption_by_default {
    sse_algorithm = "aws:kms"  kms_master_key_id = aws_kms_key.data.arn } } }
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — Multi-AZ, encrypted RDS in the data subnet
resource "aws_db_instance" "app" {
  engine                = "postgres"
  instance_class        = "db.r6g.large"
  multi_az              = true
  storage_encrypted     = true
  kms_key_id            = aws_kms_key.data.arn
  db_subnet_group_name  = aws_db_subnet_group.data.name
  backup_retention_period = 7
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — AWS Backup plan with a rule
resource "aws_backup_plan" "daily" {
  name = "daily-critical"
  rule {
    rule_name         = "daily-35d"
    target_vault_name = aws_backup_vault.immutable.name
    schedule          = "cron(0 5 * * ? *)"
    lifecycle { delete_after = 35 }
  }
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — immutable (locked) backup vault
resource "aws_backup_vault" "immutable" { name = "immutable-vault" }
resource "aws_backup_vault_lock_configuration" "lock" {
  backup_vault_name = aws_backup_vault.immutable.name
  min_retention_days = 7
  changeable_for_days = 3   # compliance mode after this window
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — restore-testing plan (REL09-BP04)
resource "aws_backup_restore_testing_plan" "quarterly" {
  name                         = "quarterly-restore-test"
  schedule_expression          = "cron(0 6 1 */3 ? *)"
  recovery_point_selection { algorithm = "LATEST_WITHIN_WINDOW"
    include_vaults = ["*"]  recovery_point_types = ["SNAPSHOT"] }
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 3 — Compute & orchestration
Example — Terraform
Terraform — Lambda in the private app subnet
resource "aws_lambda_function" "handler" {
  function_name = "rag-request"
  role          = aws_iam_role.app.arn
  runtime       = "python3.13"
  handler       = "app.handler"
  timeout       = 60
  vpc_config { subnet_ids = [for s in aws_subnet.app : s.id]
               security_group_ids = [aws_security_group.app.id] }
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — ingestion state machine (Step Functions)
resource "aws_sfn_state_machine" "ingest" {
  name     = "doc-ingestion"
  role_arn = aws_iam_role.sfn.arn
  definition = jsonencode({
    StartAt = "Parse"
    States = {
      Parse = { Type = "Task", Resource = aws_lambda_function.parse.arn, Next = "Chunk" }
      Chunk = { Type = "Task", Resource = aws_lambda_function.chunk.arn, Next = "Embed" }
      Embed = { Type = "Task", Resource = aws_lambda_function.embed.arn, Next = "Index" }
      Index = { Type = "Task", Resource = aws_lambda_function.index.arn, End = true }
    }
  })
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — EventBridge rule on S3 upload
resource "aws_cloudwatch_event_rule" "on_upload" {
  event_pattern = jsonencode({
    source = ["aws.s3"]
    "detail-type" = ["Object Created"]
    detail = { bucket = { name = [aws_s3_bucket.corpus.id] } }
  })
}
resource "aws_cloudwatch_event_target" "to_sfn" {
  rule = aws_cloudwatch_event_rule.on_upload.name
  arn  = aws_sfn_state_machine.ingest.arn
  role_arn = aws_iam_role.events.arn
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 4 — The AI layer (Bedrock + RAG)
Example — CLI
CLI — Bedrock Guardrail (input + output filters)
aws bedrock create-guardrail \
  --name rag-guardrail \
  --content-policy-config '{"filtersConfig":[
     {"type":"PROMPT_ATTACK","inputStrength":"HIGH","outputStrength":"NONE"}]}' \
  --sensitive-information-policy-config '{"piiEntitiesConfig":[
     {"type":"EMAIL","action":"ANONYMIZE"}]}' \
  --blocked-input-messaging "Blocked." \
  --blocked-outputs-messaging "Blocked."
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — Terraform
Terraform — pgvector on the existing RDS (cheap vector store)
# Enable the extension once, then create the table:
#   CREATE EXTENSION IF NOT EXISTS vector;
#   CREATE TABLE chunks (id bigserial, embedding vector(1024), body text);
#   CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops);
# (run via your migration tool against aws_db_instance.app)
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 5 — Agentic layer (only if the model must act)
Example — Terraform
Terraform — CloudWatch alarm on errors
resource "aws_cloudwatch_metric_alarm" "lambda_errors" {
  alarm_name          = "rag-request-errors"
  namespace           = "AWS/Lambda"
  metric_name         = "Errors"
  dimensions          = { FunctionName = aws_lambda_function.handler.function_name }
  statistic           = "Sum"
  period              = 60
  evaluation_periods  = 1
  threshold           = 1
  comparison_operator = "GreaterThanOrEqualToThreshold"
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 6 — Observability, evaluation & cost
Example — Terraform
Terraform — a monthly budget with an alert
resource "aws_budgets_budget" "monthly" {
  name         = "genai-monthly"
  budget_type  = "COST"
  limit_amount = "5000"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"
  notification { comparison_operator = "GREATER_THAN"
    threshold = 80  threshold_type = "PERCENTAGE"
    notification_type = "ACTUAL"
    subscriber_email_addresses = ["finops@example.com"] }
}
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Example — CLI
CLI — start a Well-Architected review
aws wellarchitected create-workload \
  --workload-name "genai-rag-platform" \
  --description "LLM+RAG+agentic platform" \
  --environment PRODUCTION \
  --lenses "wellarchitected" "genai" \
  --review-owner "security@example.com"
Illustrative starter config — adapt names, ARNs, CIDRs and regions; verify the current provider/API before use.
Phase 7 — Well-Architected review & hardening