Engineering reference: the briefing bot architecture
Same system as the rest of the series, drawn purely for engineers. Service names, resource identifiers, region, Bedrock model IDs, and the actual flow operations — everything you’d need to recreate this in your own AWS account.
Posts 1–6 walk through the system in plain language. This page is the dense version — no softening, just the architecture as you’d sketch it on a whiteboard during a design review.
Fig 7. Full architecture, ap-southeast-1. White boxes = AWS resources; dashed AWS container; dashed grey boxes = subsystem groupings; dashed grey arrows = config feed to runtimes.
Read this top-down, then column-by-column
Top row is the three external surfaces. Below it, the AWS account contains five subsystems: Build & Deploy across the top, then Config Sync, then three runtime columns (Ingestor, Ranker, Postman), with a Cross-cutting strip at the bottom. The dashed grey arrows from the Config Sync output to each runtime column show the only cross-subsystem data dependency — all three runtime Lambdas read the latest config from S3 on every invocation.
Naming conventions used in the diagram
Lambda functions:fn-<purpose> — e.g. fn-dispatcher, fn-ranker, fn-postman.
DynamoDB tables:tbl-<name> — e.g. tbl-fingerprints, tbl-digest-archive, tbl-audit.
SQS queues:q-<name> with paired q-<name>-dlq. One queue per source type.
SNS topics:t-<name> — t-alarms for general failures, t-digest-failures for SES bounces.
S3 layout: single bucket briefing-bot-data with prefixes config/, raw/{date}/, keepers/{date}.json, archive/.
Region and Bedrock model access
Everything runs in ap-southeast-1 (Singapore) for low latency from the Philippines. Bedrock model invocations use the Global cross-Region inference profile (model IDs prefixed with global.) — data at rest stays in Singapore; inference may route to other regions for capacity. Pricing is the same as on-demand Singapore pricing.
Crons are written in UTC (cron(0 22 * * ? *) = 06:00 SGT next day) so the digest lands before the operator’s morning coffee.
What’s deliberately not on the diagram
IAM policy details — per-Lambda execution role inline policies are minimal (one bucket prefix, one table, one queue as appropriate).
Per-channel delivery alternates — if you use Telegram or Slack instead of SES, the Postman column substitutes a Lambda Function URL call to the platform’s API and a corresponding secret in Secrets Manager.
X-Ray tracing — on for the Ranker Lambda only, sampling 10% — useful when tuning the similarity threshold.
The CloudFormation parameter for Bedrock model ID is templated, so swapping models doesn’t require code changes.
If you’re recreating this
Start with Build & Deploy alone (a single Lambda, no triggers). Once git push reliably updates an empty stack, add Config Sync next so you have a place to put your sources and topic. Then the Ingestor, then the Ranker, then the Postman — each on a real source, end to end, before adding the next. Cross-cutting (audit, logs, alarms, budget, watch renewer) goes in from day one.