SHAFI ANWAR

Case File

fictional demo

Nexatel AI Support Agent

Nexatel is a fictional GCC telecom company. This is a self-directed portfolio project demonstrating Solutions Engineering capability end-to-end on AWS Bedrock - not a real client engagement, and not a live production deployment for an actual telecom.

Architecture

A single Bedrock Agent with four IAM-isolated action groups, each backed by its own narrowly-scoped Lambda. Retrieval- augmented generation against real Nexatel documentation. A full production-style edge for observability and cost control.

CloudFront

Public frontend edge

API Gateway + WAF

Rate limiting · API key / usage plan

Guardrails

Content safety · topics · PII

Bedrock Agent

Single agent, orchestration

Knowledge Base

RAG over S3 Vectors

Plan Lookup

action group

Read-only: plan catalog table

Bill Inquiry

action group

Read-only: billing table

Network Status

action group

Read-only: network status table

Escalation

action group

Write-only: can create tickets, cannot read

CloudWatch

Dashboards · alarms · budget alerts

Incident Timeline

The real engineering story.

  1. 01 · INFRASTRUCTURE

    Region sustains verified physical damage

    The originally-selected region, UAE (me-central-1), sustained verified physical infrastructure damage from regional conflict and had its billing suspended - confirmed directly via AWS's own console banner.

  2. 02 · MIGRATION

    Full migration to eu-central-1

    Migrated the entire project to Frankfurt (eu-central-1) - every script, every IAM policy, every Lambda, re-verified one resource at a time.

  3. 03 · PLATFORM GATES

    Two account-verification gates, outside code or architecture

    Hit a Bedrock model-access gate requiring a use-case submission and identity verification, and a CloudFront anti-fraud account-verification gate. Both handled by opening AWS Support cases and documenting the blockers transparently.

  4. 04 · COMPLIANCE

    Caught a false compliance claim, rewrote it honest

    Mid-build, found that the compliance documentation claimed the demo satisfied UAE/GCC data-residency requirements while actually running in Germany. Rewrote the narrative: production target is UAE (me-central-1) for PDPL Article 26, the demo runs in Frankfurt because Bedrock Agents aren't yet available in me-central-1, and the architecture is region-portable by design.

Status Ledger

What's actually live versus what's pending, stated plainly. The knowledge base and the live conversational agent are pending AWS Bedrock model-access approval - everything else below is verified and running.

ResourceStatus
Lambdas (5)live
DynamoDB tables (6)live
API Gateway + WAFlive
CloudFront edgelive
CloudWatch observabilitylive
Knowledge Base ingestionpending
Live conversational agentpending

Demo

Dual-mode dashboard

Switch between configuring the agent against your own content and experiencing it as an end customer would.

Upload your use case

Simulated config preview

Source: Nexatel defaults

simulated
  • · nexatel-plan-catalog.pdf
  • · nexatel-network-sla.pdf

This preview simulates how the agent would be scoped against this content - knowledge base ingestion and the four action groups would attach here once configured.

The Problem

Telecom support teams run into the same problem everywhere: queries arrive faster than engineers can navigate the systems, documentation, and judgment calls needed to resolve them.

Success Criteria

Success was defined before writing any code.

  • Resolve plan queries automatically without human SOP lookup
  • Route billing and network requests to correct action group with accurate intent classification
  • Demonstrate production-grade IAM isolation (each Lambda scoped to only its own tables)
  • Keep infrastructure cost under $60/month at demo traffic volumes
  • Design for UAE/me-central-1 deployment once Bedrock Agents become available there

The constraints were real:

  • -Budget: effectively zero (pay-per-use only, no provisioned throughput)
  • -Timeline: 21 days, solo build, full-time employment in parallel
  • -Compliance: UAE PDPL data residency as production target
  • -Platform: hit two simultaneous AWS account-level verification gates mid-build, both had to be cleared
  • -Region: the region I started in went down mid-build - AWS confirmed physical infrastructure damage, full migration required

System Architecture

How the pieces connect.

User / BrowserCloudFront Distributioneu-central-1 · WAF attachedOAC for S3 frontendAPI Gateway REST APIRate limited · API key authRegional WAFnexatel-agent-proxy LambdaSession mgmt · consent flow · PII scrubbingAmazon Bedrock AgentClaude Sonnet 4.6 via inference profileKnowledge BaseS3 VectorsTitan embeddings · RAG retrievalplan-lookupLambdanexatel-plansbill-inquiryLambdanexatel-bills + accountsnetwork-statusLambdanetwork status dataescalationLambdanexatel-tickets

Each action group Lambda has its own IAM role scoped to only the tables it needs - no Lambda can read or write outside its designated tables.

Design Decisions

Why it was built this way.

The choices that look obvious in hindsight never are at decision time.

IAM-Isolated Action Groups

What I chose

One IAM role per Lambda, scoped to only its required tables

What I rejected

Single shared execution role with broad DynamoDB access

If a prompt injection attack tricks the agent into calling the wrong action group, the blast radius is contained. The escalation Lambda can't read billing data. The plan lookup Lambda can't create tickets. It's least privilege applied at the agent orchestration layer.

S3 Vectors over OpenSearch Serverless

OptionCostDecision
S3 Vectors~$1/mo at demo volumeSelected
OpenSearch Serverless$345/mo minimum (OCU floor)Rejected - cost
PineconeVariable, vendor lock-inRejected - external dependency

OpenSearch Serverless charges for minimum OCU capacity no matter how little you use it - $345/month even when zero queries run. At demo volumes, S3 Vectors costs under $1/month. One decision, 85% cost reduction.

eu-central-1 over me-central-1

What I chose

AWS Europe (Frankfurt)

What I rejected

AWS Middle East (UAE) - the intended production region

Bedrock Agents and the models I needed aren't available in me-central-1. The Bedrock control plane doesn't respond there - no bedrock-runtime or bedrock-agent endpoints exist in the region. eu-central-1 is the nearest region with full support. The production target is still me-central-1 for PDPL Article 26 compliance, documented clearly rather than buried.

96-Hour Escape Hatch

What I chose

Deterministic EventBridge Scheduler timer that auto-releases stuck cases

What I rejected

Trusting downstream service teams to always respond within SLA

In any distributed async system, you have to design for the stuck state. Service teams have SLAs but not guarantees. Without a timeout, a single unresponsive ticket locks a customer case permanently. 96 hours is four business days before the fail-safe fires. Any customer reply while the case is locked also releases it immediately.

Honest Compliance Framing

What I chose

Documenting the data-residency exception explicitly in all compliance materials

What I rejected

Claiming PDPL Article 26 compliance for a Frankfurt deployment

eu-central-1 is Germany, not the UAE. Writing 'data does not leave GCC territory' for a Frankfurt deployment would be false. The accurate framing is also the more credible one - a technical interviewer knows what overclaimed compliance looks like. Every real system has constraints. Documenting them clearly is part of the job.

Scalability

What changes when traffic grows.

1,000 conversations / month

current demo

  • -Architecture: as documented above
  • -Bedrock: on-demand inference, no provisioning
  • -Cost: $23-55/month
  • -Bottleneck: none at this volume

10,000 conversations / month

  • -Add: DynamoDB DAX for session read caching
  • -Add: Lambda reserved concurrency to prevent cold start latency spikes
  • -Consider: Bedrock provisioned throughput for Sonnet if token costs exceed $300/month
  • -Cost: ~$200-400/month
  • -Bottleneck: Knowledge Base retrieval latency starts to matter

1,000,000 conversations / month

production telecom

  • -Replace: DynamoDB on-demand with provisioned capacity + auto-scaling
  • -Add: ElastiCache Redis for session state (reduces DynamoDB read load 80%)
  • -Add: SQS queue in front of agent-proxy Lambda for burst absorption
  • -Add: Multi-region active-passive with Route 53 health checks and failover
  • -Add: Bedrock provisioned throughput (dedicated model capacity)
  • -Replace: Single Knowledge Base with per-tenant Knowledge Bases for multi-carrier deployment
  • -Add: GuardDuty, Security Hub, AWS Organizations SCPs for enterprise governance
  • -Cost: $8,000-15,000/month
  • -Bottleneck: Bedrock token throughput limits become the primary constraint

Operational Ownership

How the system is monitored and recovered.

Observability

CloudWatch dashboard: Nexatel-Support-Agent
Metrics published to Nexatel/SupportAgent namespace:
  - ConversationCount        - total requests (Count)
  - ConversationLatencyMs    - p95 target <3000ms (ms)
  - ConsentGranted           - consent flow completions
  - DataDeletionRequest      - PDPL deletion requests
  - TicketCreated            - escalation rate

Alarms configured:
  - HighErrorRate:  API Gateway 5XX > 5 in 5 min -> SNS alert
  - HighLatency:    ConversationLatencyMs p95 > 10s -> SNS alert
  - Budget:         $50/month threshold, alerts at 80% and 100%

Incident Response

Runbook for a latency spike:

  • 1.Check ConversationLatencyMs in dashboard - identify whether spike is in agent-proxy (session/consent overhead) or Bedrock (model invocation)
  • 2.If Bedrock: check AWS Health Dashboard for eu-central-1 Bedrock service status
  • 3.If agent-proxy: check Lambda duration metrics - cold start vs warm execution
  • 4.Rollback path: Lambda has versioned deployments - previous version can be restored in <2 minutes

Deployment

Zero-downtime Lambda updates via infrastructure/05_deploy_lambdas.py - update_function_code followed by immediate smoke test invoke. If smoke test fails, previous deployment is still active. No blue/green required at current scale.

What Broke

The things that didn't work the first time.

Every real system has a failure log. Most portfolios don't show theirs.

Region Infrastructure Failure

Impact: Full project migration required mid-build

What happened

The region I started with - me-central-1 in the UAE - went down mid-build. AWS confirmed billing was suspended due to verified physical infrastructure damage.

How resolved

Migrated the whole project to eu-central-1 - every script, IAM policy, and Lambda redeployed and re-verified. Also discovered Bedrock Agents aren't available in me-central-1 anyway, so the migration was right for two reasons.

Bedrock Account Verification Gate

Impact: Blocked KB ingestion and agent creation for multiple days

What happened

Titan and Claude Sonnet 4.6 kept returning NOT_AUTHORIZED even with AdministratorAccess. The standard use-case intake form returned 'not authorized' too - the normal resolution path was blocked.

How resolved

Turned out to be an account-level KYC gate. Submitted identity verification, opened a Support case, and escalated to the Bedrock Marketplace team. Titan cleared first. Sonnet took additional escalation. Documented in CLAUDE.md.

CloudFront Account Verification

Impact: Public edge deployment blocked

What happened

create_distribution came back AccessDenied at step 11 of the deployment script. Steps 1 through 10 had already run successfully.

How resolved

An AWS Support case cleared the verification. The script was idempotent - re-run skipped the 10 already-created resources and only ran the CloudFront step.

False Compliance Documentation

Impact: Compliance narrative required full correction across all files

What happened

An earlier version of the docs claimed data was stored in 'AWS Middle East (UAE) region (eu-central-1).' eu-central-1 is Frankfurt, Germany - not the UAE.

How resolved

Ran grep across every file, rewrote the compliance narrative with an explicit data-residency exception, updated the consent message, all script docstrings, and the README. One accurate story, everywhere.

Production Economics

What this costs to run.

Estimated at 1,000 customer conversations per month.

ServiceMonthly Cost
Amazon Bedrock (Sonnet 4.6)$15-45
S3 Vectors (Knowledge Base)<$1
AWS Lambda (5 functions)~$0.50
API Gateway~$3.50
DynamoDB (6 tables)~$1-3
CloudFront~$1
CloudWatch + alarms~$2
WAF (2 web ACLs)~$12
KMS (CMK)~$1
Secrets Manager~$0.40
Total$36-69/month

The S3 Vectors decision reduced cost 85% vs OpenSearch Serverless ($345/month minimum). That single architecture choice keeps the entire stack within a reasonable demo budget.

At 10,000 conversations/month, Bedrock token costs dominate (~$150-450/month). Everything else remains nearly flat.

Architecture Review

The questions a Principal SA would ask.

Every architecture has tradeoffs. Here are the hard questions and honest answers.

Why Bedrock Agents instead of LangGraph?

LangGraph is framework-level orchestration - you own the runtime, the hosting, and the integration layer. Bedrock Agents is a managed AWS service with action group routing, Knowledge Base integration, and Guardrails built in. For a system that needs IAM-controlled access to DynamoDB and Secrets Manager, native AWS orchestration removes a whole category of complexity. LangGraph is the documented path forward for multi-agent scenarios.

Why REST API instead of HTTP API?

HTTP API is cheaper and faster, but it doesn't support request validation or usage plans with API key auth - both of which I needed. The API key gates every /chat request, and request validation enforces the JSON schema before anything hits Lambda. HTTP API doesn't do either natively. REST API was the right call.

Why synchronous instead of event-driven for the main conversation flow?

Chat is synchronous by nature - a customer waiting for a reply can't wait for a queue. The Bedrock Agent invocation is synchronous by design. Async is used only where it belongs: the Route 53 SQIR automation, where the system hands off to a service team and waits hours or days for resolution.

What breaks first at scale?

Bedrock token throughput limits. On-demand inference has soft limits per region, and around 50 to 100 concurrent conversations you start hitting throttling. The fix is provisioned throughput for Sonnet 4.6 - guaranteed capacity at a predictable cost. This is the documented first scaling action.

What is the RTO and RPO?

For the demo: RTO is roughly 5 minutes - Lambda cold starts plus API Gateway propagation after a redeploy. RPO is effectively zero because DynamoDB is durable and no data lives in Lambda memory between invocations. For a production telecom system: RTO target under 60 seconds means multi-AZ Lambda and DynamoDB global tables. RPO under 1 minute means point-in-time recovery enabled.

Which AWS Well-Architected pillars are strongest?

Strongest: Security - IAM isolation, KMS CMK, WAF, Secrets Manager, Guardrails, no credentials in code. And Operational Excellence - CloudWatch custom metrics, alarms, budget alerts, idempotent scripts. Weakest is Reliability at scale: single-region, no automatic failover, and no load testing to validate concurrent behavior.

How would you reduce cost another 40%?

Three levers. First, prompt compression - the system prompt is verbose and cutting it by 40% reduces input token cost proportionally. Second, response caching - common queries like 'what is the Starter plan?' could be cached in ElastiCache with a 1-hour TTL, bypassing Bedrock entirely for repeated questions. Third, switch plan lookup and network status to Claude Haiku 4.5 where reasoning depth isn't needed, and reserve Sonnet for billing disputes and escalation.

What would you build differently with six more months?

Multi-tenant architecture first. The current build is single-tenant and a real product needs per-tenant Knowledge Bases, tenant-level IAM isolation, and usage metering. Second, a feedback loop - score every agent response against whether the customer resolved their issue and feed that back into Knowledge Base refinement. Third, Arabic language support. The GCC market is bilingual and a support agent that can't handle Arabic isn't ready for production deployment.