ADR-002: Cross-Region Bedrock Architecture for Image Generation

Status

Accepted

Date

2025-12-10

Context

Momentum’s AI-powered course generation requires thumbnail images generated using AI models. We evaluated several options:

  1. Amazon Titan Image Generator - Available in us-east-1 (our primary region), but produces lower-quality results
  2. Stability AI SDXL - Available in us-east-1, but produces inconsistent quality for educational thumbnails
  3. Stability AI SD 3.5 Large - Produces the highest-quality images, but is only available in us-west-2

Our primary infrastructure is deployed in us-east-1 (API Gateway, Lambda, Aurora, S3, Cognito). The best image generation model (Stable Diffusion 3.5 Large) is only available in us-west-2.

Key Constraints

  • SD 3.5 Large is only available in specific regions (us-west-2, eu-west-1, ap-northeast-1)
  • All other infrastructure (database, API, authentication) is in us-east-1
  • Bedrock model invocation is synchronous - no async option available
  • Thumbnail generation is part of the course generation workflow (Step Functions)

Decision

We adopted a cross-region Bedrock invocation pattern where:

  1. Lambda functions remain in us-east-1 with the rest of the infrastructure
  2. Bedrock calls for SD 3.5 Large are made cross-region to us-west-2
  3. Generated images are uploaded to S3 in us-east-1 (same region as other assets)

Implementation Details

Lambda Configuration

The generate-thumbnail Lambda:

  • Deployed in us-east-1 (same as other Lambdas)
  • Invokes Bedrock SD 3.5 Large in us-west-2
  • Does NOT use VPC (only needs public AWS endpoints)
  • Uploads generated images to S3 in us-east-1
// Lambda creates a Bedrock client targeting us-west-2
const BEDROCK_IMAGE_REGION = process.env.BEDROCK_IMAGE_REGION || 'us-west-2';
const bedrockClient = new BedrockRuntimeClient({ region: BEDROCK_IMAGE_REGION });

IAM Policy Configuration

The Lambda execution role has two separate Bedrock policy statements:

# Primary region models (us-east-1)
{
  Sid    = "AllowBedrockModelInvocation"
  Effect = "Allow"
  Action = ["bedrock:InvokeModel"]
  Resource = [
    "arn:aws:bedrock:${var.aws_region}::foundation-model/anthropic.claude-*",
    "arn:aws:bedrock:${var.aws_region}::foundation-model/amazon.titan-image-generator-v2:0"
  ]
}

# Cross-region model (us-west-2 for SD 3.5 Large)
{
  Sid    = "AllowBedrockSD35LargeInvocation"
  Effect = "Allow"
  Action = ["bedrock:InvokeModel"]
  Resource = [
    "arn:aws:bedrock:us-west-2::foundation-model/stability.sd3-5-large-v1:0"
  ]
}

Environment Variables

environment {
  variables = {
    BEDROCK_IMAGE_MODEL_ID = "stability.sd3-5-large-v1:0"
    BEDROCK_IMAGE_REGION   = "us-west-2"  # Cross-region target
  }
}

Why No VPC for Thumbnail Lambda

The thumbnail generation Lambda intentionally runs without VPC configuration:

  1. No database access needed - receives course metadata from Step Functions state
  2. Only uses public AWS endpoints - Bedrock and S3 are accessible via public internet
  3. Faster cold starts - no ENI attachment delay (saves 5-10 seconds)
  4. No NAT gateway costs - no outbound traffic through VPC

Consequences

Positive

  1. Highest quality thumbnails - SD 3.5 Large produces significantly better results than alternatives
  2. No infrastructure migration - Core infrastructure remains in us-east-1
  3. Minimal latency impact - Cross-region Bedrock call adds ~50-100ms
  4. Cost-effective - No NAT gateway, no cross-region data transfer for final assets
  5. Simple architecture - Single Lambda invokes multiple regions as needed
  6. Future-proof - Can easily add other region-specific models

Negative

  1. Region availability dependency - If us-west-2 Bedrock has issues, thumbnail generation fails
  2. Cross-region IAM complexity - Need separate policy statements per region
  3. Monitoring complexity - Need to monitor Bedrock metrics in both regions
  4. Pricing variation - Model pricing may differ between regions

Risks and Mitigations

Risk Mitigation
us-west-2 Bedrock outage Workflow continues without thumbnail; can regenerate later
Model deprecation Environment variable allows quick model switch
Increased latency Acceptable for batch operations; not user-facing
Cost unpredictability SD 3.5 Large pricing is predictable per-image

Alternatives Considered

Alternative 1: Multi-Region Lambda Deployment

Deploy a separate Lambda in us-west-2 for image generation.

Rejected because:

  • Increased infrastructure complexity
  • Need for cross-region S3 transfer
  • Additional deployment pipeline
  • Higher maintenance burden

Alternative 2: Use Lower-Quality Model in us-east-1

Use Amazon Titan or SDXL in us-east-1 instead.

Rejected because:

  • Significantly lower image quality
  • Thumbnails are customer-facing assets
  • Quality directly impacts course appeal

Alternative 3: Migrate All Infrastructure to us-west-2

Move everything to a region with SD 3.5 Large.

Rejected because:

  • Major infrastructure change
  • Potential latency impact for users
  • us-east-1 has better service availability overall
  • Disruption to existing services

Alternative 4: Use External Image Generation API

Use Stability AI’s direct API instead of Bedrock.

Rejected because:

  • Additional vendor relationship
  • Separate billing and authentication
  • Loss of Bedrock’s unified interface
  • Potential compliance concerns

References


Back to top

Momentum LMS © 2025. Distributed under the MIT license.