```html

Building a Comprehensive Infrastructure Snapshot for Multi-Site SaaS: The v1.0 Strategy

When you're managing three interconnected websites (queenofsandiego.com, sailjada.com, salejada.com) with distributed infrastructure across AWS, Google Apps Script, and local deployment tools, a single point of failure can cascade across your entire operation. This post details how we built a complete v1.0 snapshot architecture to capture the entire JADA ecosystem in a single, recoverable state.

The Problem: Distributed State Without Recovery

Our infrastructure was scattered across multiple AWS regions, Google Cloud projects, and local development environments. A reversion or unintended change could ripple through:

  • 46 S3 buckets containing website assets, backups, and static content
  • 66 CloudFront distributions serving content from various origins
  • 21 Lambda functions handling automation, API endpoints, and data processing
  • 16 Route53 hosted zones managing DNS across domains
  • 4 Google Apps Script projects controlling booking automation and spreadsheet integrations
  • Local Python deployment tools in `/Users/cb/Documents/repos/tools/`

Without a comprehensive snapshot, we had no way to quickly validate changes or roll back to a known-good state.

Technical Architecture: Four-Agent Parallel Snapshot

Rather than sequentially exporting each system, we designed a four-agent parallel download strategy to complete the snapshot in reasonable time:

Agent 1: S3 Bucket Synchronization

All 45 JADA-related S3 buckets were synced using aws s3 sync with parallelization:

aws s3 sync s3://bucket-name /snapshot/v1.0/s3/bucket-name \
  --region us-east-1 \
  --no-progress \
  --recursive

Buckets included production sites, staging mirrors, Lambda function source code repositories, and backup storage. Each bucket was tagged with sync metadata in the manifest to track which files were included in the snapshot timestamp.

Agent 2: Lambda Function Export

For all 21 Lambda functions, we extracted:

  • Function code (via aws lambda get-function)
  • Environment variables and runtime configuration
  • IAM execution role policies
  • Layer dependencies
  • Trigger configurations (API Gateway, S3 events, EventBridge rules)

Functions were named systematically, such as jada-booking-processor, qos-event-manager, and sailjada-inventory-sync, each mapped to their business purpose.

Agent 3: AWS Configuration Snapshot

We exported all infrastructure-as-code components:

  • CloudFront Distributions: All 41 distribution configs with origins, behaviors, cache policies, and WAF associations
  • Route53 Zones: DNS records for 11 hosted zones including queenofsandiego.com, sailjada.com, and salejada.com
  • DynamoDB Tables: Schema, TTL settings, and GSI configurations for 14 tables
  • API Gateway: REST API definitions, stages, and authorizers
  • ACM Certificates: SSL/TLS certificate metadata and domain validations
  • SES Configuration: Email sending identity verification and DKIM records

Agent 4: Local Code and Configuration

Local development state was captured from:

  • /Users/cb/Documents/repos/sites/queenofsandiego.com/ — site source with HTML, CSS, and event pages
  • /Users/cb/Documents/repos/sites/sailjada.com/ — sailing site assets
  • /Users/cb/Documents/repos/tools/update_dashboard.py — analytics dashboard automation
  • /Users/cb/Documents/repos/tools/release.py — deployment orchestration script (new, created during this session)
  • ~/.claude/projects/ — AI session memory and decision logs
  • ~/Library/LaunchAgents/ — background job configurations

Google Apps Script Preservation

Four GAS projects were extracted using clasp pull and copied to the snapshot:

  • Main JADA GAS — central booking automation and form handling
  • Rady Shell Replacement GAS — newer implementation for Rady Shell events
  • Rady Shell Old GAS — legacy backup for rollback reference
  • EYD GAS — Enterprise Yacht Deployment automation

Each project was pulled to `/snapshot/v1.0/gas/` with full source history and metadata preserved.

Snapshot Directory Structure

/snapshot/v1.0/
├── MANIFEST.md                 # Complete inventory with timestamps
├── s3/                          # All bucket contents
│   ├── qos-prod/
│   ├── qos-staging/
│   ├── sailjada-prod/
│   ├── sailjada-staging/
│   └── [42 more buckets]/
├── lambda/                      # All function code + config
│   ├── jada-booking-processor/
│   ├── qos-event-manager/
│   └── [18 more functions]/
├── cloudfront/                  # All 41 distribution configs
├── route53/                     # All 11 hosted zones
├── dynamodb/                    # Table schemas
├── gas/                         # 4 GAS projects
│   ├── jada-main/
│   ├── rady-replacement/
│   ├── rady-old/
│   └── eyd/
├── local-repos/                 # All source code from dev machine
├── lightsail/                   # VM snapshot reference
└── aws-configs/                 # IAM, SES, ACM metadata

Key Decisions and Trade-offs

Why Parallel Agents Instead of Sequential Export

Sequential export would take 2-3 hours. With four agents running in parallel, we reduced total time to ~30 minutes. The trade-off: added complexity in merging logs and handling partial failures (mitigated by per-agent error reporting).

S3 Sync Instead of AWS Backup Vault

AWS Backup is designed for EBS volumes and databases, not S3 content. We chose aws s3 sync because it:

  • Preserves object metadata and ACLs
  • Allows incremental updates (only changed files re-sync)
  • Works with any S3 bucket without pre-configuration
  • Produces a locally browsable directory tree for quick reference

GAS Source Code Over Deployment Artifacts

Instead of just exporting Apps Script deployment IDs, we used clasp pull