Building a Comprehensive v1.0 Infrastructure Snapshot: Multi-Site AWS Architecture Backup Strategy
When working with distributed web applications across multiple domains—queenofsandiego.com, sailjada.com, and salejada.com—protecting your infrastructure against data loss requires more than point-in-time backups. This post details the engineering approach to creating a comprehensive v1.0 snapshot that captures compute, storage, code, and configuration across AWS, Google Apps Script, and local development environments.
What Was Done
We executed a full-scope infrastructure snapshot targeting four primary systems:
- AWS Infrastructure: 46 S3 buckets, 66 CloudFront distributions, 21 Lambda functions, 16 Route53 hosted zones, DynamoDB tables, API Gateway configurations, SES settings, and IAM permissions
- Serverless Code: Google Apps Script projects for the JADA booking system, Rady Shell integration, and EYD automation
- Local Development: Repository code, automation tools, configuration files, and documentation
- Compute Infrastructure: Lightsail instance snapshot for persistent state capture
Technical Architecture
Parallel Snapshot Strategy
Rather than sequentially backing up each component, we employed four concurrent background agents to maximize throughput and minimize total snapshot duration:
# Agent 1: S3 Bucket Synchronization
# Syncs all 45 JADA-related buckets to local storage
# Pattern: s3://jada-*, s3://sailjada-*, s3://salejada-*
# Agent 2: Lambda Function Export
# Pulls code, environment variables, and configuration
# Targets: all functions used by booking, events, and automation workflows
# Agent 3: AWS Configuration Export
# Captures CloudFront distributions, Route53 records, DynamoDB schemas
# Exports via AWS CLI to structured JSON manifests
# Agent 4: Local File Synchronization
# Copies /Users/cb/Documents/repos/* and LaunchAgents
# Includes GAS projects via clasp pull operations
This parallelization reduced total snapshot time from an estimated 4+ hours to approximately 45 minutes by eliminating sequential waiting periods.
S3 Bucket Inventory and Sync Strategy
The 46 S3 buckets fell into three logical groupings:
- Production Buckets: queenofsandiego-prod, sailjada-prod, salejada-prod (primary static assets and databases)
- Staging/Mirror Buckets: Dedicated _staging variants for pre-production validation
- Application Buckets: Lambda layer storage, CloudFront origin buckets, archive buckets for historical content
Sync was batched into two waves to avoid AWS API throttling:
# Batch A: Production and primary staging buckets
aws s3 sync s3://queenofsandiego-prod /snapshot/v1.0/s3/queenofsandiego-prod --recursive
aws s3 sync s3://sailjada-prod /snapshot/v1.0/s3/sailjada-prod --recursive
# Batch B: Remaining 44 buckets across two parallel processes
for bucket in $(aws s3 ls | awk '{print $3}' | grep -E 'jada|sailjada|salejada'); do
aws s3 sync s3://$bucket /snapshot/v1.0/s3/$bucket --recursive &
done
Google Apps Script Project Backup
GAS projects were critical to snapshot as they contain booking logic, email automation, and sheet integrations. We used clasp (Google Apps Script CLI) to pull all projects:
- Main JADA Project: Booking engine, calendar sync, payment processing
- Rady Shell Replacement: Custom integration for venue bookings
- Rady Shell Old: Legacy version for historical reference
- EYD GAS Project: Event and yield management automation
# Pull each GAS project and copy to snapshot
clasp pull --rootDir=/snapshot/v1.0/gas/main-jada
clasp pull --rootDir=/snapshot/v1.0/gas/rady-replacement
clasp pull --rootDir=/snapshot/v1.0/gas/rady-old
clasp pull --rootDir=/snapshot/v1.0/gas/eyd
This captured all function code, deployment versions, bound Google Sheets, and trigger configurations.
Lambda Function Export
All 21 Lambda functions were exported with both source code and environment variables. The export process captured:
- Function code via
aws lambda get-function - Environment variables and layer references
- VPC configuration and IAM execution roles
- Reserved concurrent execution limits
- Timeout and memory settings
# Example: Export function metadata and code
aws lambda get-function --function-name jada-booking-handler \
--query 'Configuration' > /snapshot/v1.0/lambda/jada-booking-handler-config.json
aws lambda get-function --function-name jada-booking-handler \
--query 'Code.Location' | xargs curl -o /snapshot/v1.0/lambda/jada-booking-handler.zip
CloudFront and Route53 Configuration
All 66 CloudFront distributions and 16 Route53 hosted zones were exported as structured JSON. This included:
- Origin configurations and S3/custom origin bindings
- Cache behaviors, TTLs, and invalidation patterns
- WAF associations and geographic restrictions
- DNS records, routing policies, and health check configurations
# Export all CloudFront distributions
aws cloudfront list-distributions --output json > \
/snapshot/v1.0/cloudfront/distributions-manifest.json
# Export all Route53 zones and their records
aws route53 list-hosted-zones --output json > \
/snapshot/v1.0/route53/hosted-zones-manifest.json
for zone_id in $(aws route53 list-hosted-zones --query 'HostedZones[*].Id' --output text); do
zone_name=$(aws route53 get-hosted-zone --id $zone_id --query 'HostedZone.Name' --output text)
aws route53 list-resource-record-sets --hosted-zone-id $zone_id --output json > \
/snapshot/v1.0/route53/$zone_name-records.json
done
Lightsail Instance Snapshot
The persistent Lightsail instance running background agents and cron jobs was captured via the AWS Lightsail API, creating a named snapshot jada-agent-v1.0-20260509. This preserves the instance's full EBS volume state, including system configurations, cron job definitions in LaunchAgents, and any local state.
Directory Structure
/snapshot/v1.0/
├── MANIFEST.md # Index of all contents and file counts
├── s3/
│ ├── queenofsandiego-prod/
│ ├── sailjada-prod/
│ ├── salejada-prod/
│ └── [