The complete architecture

Private Assets

Published:

We started with an empty account and a deployable S3 bucket. The completed application lets an authenticated owner upload a private image, follow its processing, inspect automatically detected labels, and request a temporary private download. Around that flow, we added independently delivered events, operational visibility, request filtering, and a repeatable preview lifecycle.

This final diagram brings the services from all thirteen implementation chapters together. It shows the architecture after the WAF chapter: the REST API has replaced the HTTP API, and private S3 download grants have replaced public processed-asset delivery.

Complete AWS architecture: protected website and API paths with Cognito and owner checks; direct private S3 transfers; SQS admission to a Step Functions workflow using Lambda and Rekognition; DynamoDB metadata; EventBridge and SNS lifecycle delivery with separate recovery queues; CloudWatch operations and KMS; and GitHub OIDC, IAM, STS, CDK, CloudFormation, bootstrap S3 and Systems Manager Parameter Store, optional Budgets, and the CloudTrail account guardrail.

Open full-size PNG · Open vector image

Read it as one asset's journey #

The browser loads the page through the CloudFront web ACL and distribution, with a private S3 site origin. Cognito's hosted UI handles sign-in. The page then calls the regional REST API directly, through its own WAF association. Protected methods validate the current preview client's ID token before invoking Lambda; the handlers use DynamoDB ownership records to decide what that caller may access. Cognito supplies the authorizer configuration, rather than becoming a forwarding hop between the API and Lambda.

The upload API returns a constrained signed S3 form. Image bytes go directly to the private asset bucket, whose upload notification enters SQS. A starter Lambda hands the asset to a Standard Step Functions execution. Task Lambdas validate and copy it; Step Functions calls Rekognition directly on the processed object version. Completion saves ready state and the compact labels together in DynamoDB. The owner reads that result through the status API and requests a short-lived S3 download grant. Direct uploads and downloads remain outside both WAF associations.

Only after a terminal state is saved does the workflow publish its lifecycle fact. EventBridge independently routes it to the audit log and lifecycle SNS topic. SNS delivers all outcomes to the integration SQS queue and, when configured and confirmed, rejected or failed outcomes to email. The demonstration integration queue has no automatic application consumer. Subscribers can react later without deciding whether the image is ready. Database persistence and event publication remain separate writes, so a publication failure can coexist with a saved terminal result.

Keep failures and observations separate #

SQS retries a failed workflow admission; Step Functions owns retries after an execution starts. EventBridge and SNS own their respective target and subscription deliveries. Four mandatory DLQs and an optional email DLQ preserve those different recovery boundaries. The poster groups them visually; the implementation keeps the queues separate.

CloudWatch brings service metrics, alarms, logs, and recent lifecycle events into an operator's view. WAF records blocked-request evidence in its own protected log groups. A separate SNS topic carries alarm and recovery messages, so an operational alert does not enter the asset integration queue or its lifecycle filters. AWS KMS supplies the rotating customer managed key used by both SNS topics. An operator still has to investigate and repair a failure; an alarm does not rewrite metadata or replay work.

The foundation outlives a preview #

GitHub Actions obtains temporary AWS role credentials through OIDC, IAM trust, and STS. CDK synthesizes the infrastructure and stages deployment assets; CloudFormation manages the resulting resources. Its bootstrap S3 bucket is separate from the site's bucket and the private asset bucket. Systems Manager Parameter Store supports bootstrap checks and CDK's cross-region references; it does not store application asset metadata. The diagram's role chain describes deployment authority, not application traffic.

The existing workflows deploy an application stack in the configured Region and a companion CloudFront WAF stack in us-east-1. They remove both preview stacks in dependency order when the pull request closes. The shared Cognito pool, account access setup, and any optional budget configuration live outside that disposable preview lifecycle.

AWS Budgets is the optional cost-alert guardrail from the first chapter. CloudTrail is shown as that chapter's account audit guardrail; the application source does not provision a trail. Budget email, lifecycle email, and alarm email have separate configuration and delivery behavior. None of these email paths introduces Amazon SES into the application.