06 - Architecture Patterns and Cost Optimization¶
This note ties services together into common patterns the exam asks about.
Pattern 1 - Lakehouse on S3 with Iceberg¶
Sources (RDBMS, SaaS, files)
β
ββ DMS (full + CDC) βββββ
ββ AppFlow ββββββββββββββ€
ββ Transfer Family ββββββ€
ββ Kinesis Firehose βββββ΄βββ S3 (raw, partitioned)
β
βΌ
Glue ETL (Spark)
β
βΌ
S3 Iceberg (curated)
β
βββββββββΌβββββββββ
βΌ βΌ βΌ
Athena Redshift EMR
Spectrum
Why Iceberg¶
- ACID transactions
- Schema evolution
- Time travel for reproducible queries
- Hidden partitioning (no Hive-style directory layout required)
- Cross-engine compatibility (Athena, Glue, EMR, Redshift Spectrum, Spark)
Cost optimizations¶
- Partition by query-predicate columns (date, region).
- Compact small files via Iceberg
OPTIMIZE. - Parquet + Snappy.
- S3 lifecycle to Glacier for cold partitions.
Pattern 2 - Streaming pipeline (lambda / kappa)¶
Kappa (single streaming path)¶
Producers βββΆ Kinesis Data Streams
β
βββΆ Managed Flink (real-time aggregation)
β β
β βββΆ DynamoDB (state) + OpenSearch (dashboards)
β
βββΆ Firehose βββΆ S3 (Parquet)
β
βββΆ Athena (ad-hoc historical)
Lambda architecture (batch + streaming)¶
Streaming path:
Kinesis βββΆ Flink βββΆ DynamoDB / OpenSearch (real-time view)
Batch path:
Kinesis βββΆ Firehose βββΆ S3 βββΆ Glue ETL βββΆ Iceberg βββΆ Redshift / Athena (corrected view)
When to choose what¶
- Kappa simpler; reprocess by replaying Kinesis or re-running on the S3 archive.
- Lambda when batch needs different (more accurate / heavier) transformations than streaming can handle.
Pattern 3 - CDC to lakehouse¶
RDS Postgres
β
βββΆ DMS (full load + CDC)
β
βββΆ S3 (raw CDC events as JSON)
β
βββΆ Glue ETL (Spark with Iceberg writer)
β
βββΆ S3 Iceberg (merge upserts/deletes)
β
βββΆ Athena / Redshift Spectrum
For Aurora source: prefer Aurora Zero-ETL to Redshift / OpenSearch instead of DMS when the destination is one of those (less infra to manage).
Pattern 4 - Operational data store with analytics offload¶
Application
β
βΌ
DynamoDB (sub-ms reads/writes)
β
βββΆ DAX (microsecond read cache)
β
βββΆ DynamoDB Streams βββΆ Lambda βββΆ Kinesis Firehose βββΆ S3 βββΆ Athena
β
βββΆ DynamoDB Export to S3 (full / incremental, no consumed capacity)
β
βββΆ Iceberg / Athena / EMR for analytics
For RDS / Aurora: Aurora Zero-ETL to Redshift / OpenSearch is the modern equivalent.
Pattern 5 - Multi-account data mesh¶
Account A (Producer)
ββ S3 + Glue Data Catalog + Lake Formation
β
βββΆ LF cross-account share (via LF-Tags)
Account B (Consumer)
ββ Resource link to shared database
β
βββΆ Athena / Redshift Spectrum / Glue ETL
Account C (Consumer)
ββ Same pattern
Why Lake Formation cross-account share:
- No data copy
- Centralized governance in producer account
- Tag-based access control scales to many tables
- Auditable via CloudTrail
Pattern 6 - Hot / warm / cold tiering¶
Hot - DynamoDB / OpenSearch / Redshift RA3
Warm - S3 Standard / Standard-IA + Athena
Cold - S3 Glacier Instant Retrieval / Flexible Retrieval
Frozen - S3 Glacier Deep Archive
Lifecycle policies move data automatically based on age. Match the tier to the access pattern, not the data age alone (Intelligent-Tiering is the safe default if unsure).
Pattern 7 - Orchestrated batch ETL¶
EventBridge schedule (cron)
β
βββΆ Step Functions Standard
β
βββΆ Glue Crawler (discover new partitions)
β
βββΆ Map state (per source table):
β βββΆ Glue ETL job
β βββΆ Glue Data Quality
β
βββΆ Athena CTAS (publish curated tables)
β
βββΆ Lambda (post-success notifications)
β
βββΆ Catch βββΆ SNS / Slack / DLQ on failure
Variant: MWAA (Airflow) when the team's existing skills are Airflow-based.
Pattern 8 - Real-time alerting from streaming KPIs¶
Producers βββΆ KDS βββΆ Managed Flink (windowed agg)
β
βββΆ CloudWatch Custom Metric
β
βββΆ CloudWatch Alarm βββΆ SNS / Lambda
Or for simpler thresholds: Lambda consumer on KDS that emits metrics and triggers alarms directly.
Cost-optimization playbook¶
S3¶
- Parquet over JSON / CSV
- Snappy compression
- Partition by query predicates
- Lifecycle to cheaper classes
- Intelligent-Tiering when access pattern is unknown
- Multipart upload for >100 MB
- Inventory + Storage Lens to find waste
Athena¶
- Workgroup data scan limits per team
- CTAS to materialize repeat-use datasets
- Result reuse cache
- Partition projection for high-cardinality partitions
- Federated queries for "ingest avoidance" when joining one-off
Glue¶
- Job bookmarks
- Push-down predicates
- Right-size workers (start with G.1X)
- Glue 4.0/5.0 for newest Spark
- Use Spot for EMR alternative when Spark workload is heavy
EMR¶
- Spot for task nodes (recoverable)
- Auto-termination
- Graviton (m7g/r7g) for cost savings
- EMR Serverless for spiky / unpredictable workloads
- Persist data in S3 (EMRFS), use HDFS only as scratch
Redshift¶
- RA3 + Reserved Instances for steady workloads
- Serverless for spiky / intermittent
- Concurrency Scaling for read bursts (free credits available)
- Materialized views for repeated heavy aggregations
- Result caching reduces repeat-query cost
- Data sharing instead of copies for cross-team analytics
Kinesis / Firehose / MSK¶
- KDS On-Demand only for unpredictable; Provisioned for predictable
- Firehose: large buffer sizes reduce S3 PUT cost; GZIP + Parquet conversion
- MSK Serverless when workload is variable
DynamoDB¶
- On-demand for unpredictable
- Provisioned + auto-scaling for predictable
- Reserved capacity for very steady, large
- DAX only when microsecond reads are required (it's expensive)
Reliability patterns¶
| Pattern | Tooling |
|---|---|
| Dead letter queue | SQS DLQ on Lambda async / SNS / Step Functions |
| Idempotency | Idempotency keys; Iceberg merge-on-read |
| Retries with backoff | Step Functions Retry; SDK retries |
| Circuit breakers | Custom Lambda logic; AWS App Mesh |
| Replay | Kinesis retention (24h-365d); replay from S3 archive |
| Multi-region DR | Aurora Global Database; S3 CRR; DynamoDB Global Tables; Redshift cross-region snapshot copy |
Decision flowcharts¶
"Where do I put this data?"¶
Need single-digit ms key-value? βββΆ DynamoDB
Need OLTP relational? ββββββββββββΆ RDS or Aurora
Need MPP SQL warehouse? ββββββββββΆ Redshift
Need search / log analytics? βββββΆ OpenSearch
Need cheap durable lake? βββββββββΆ S3 (+ Iceberg if ACID needed)
Need cache? ββββββββββββββββββββββΆ ElastiCache or DAX
"How do I move this data?"¶
Real-time (sub-sec)? βββββββΆ Kinesis Data Streams
Real-time β S3/Redshift? βββΆ Kinesis Firehose
Apache Kafka? ββββββββββββββΆ MSK
Database CDC? ββββββββββββββΆ DMS (or Aurora Zero-ETL)
SaaS source? βββββββββββββββΆ AppFlow
SFTP / FTP? ββββββββββββββββΆ Transfer Family
Bulk migration NFS / SMB? ββΆ DataSync (or Snowball offline)
Catalog new files? βββββββββΆ Glue Crawler
"How do I transform this?"¶
Spark batch with no infra? βββΆ Glue ETL (or EMR Serverless)
Long-running Spark / Hive? βββΆ EMR on EC2
Lightweight per-record? ββββββΆ Lambda
Visual ETL? ββββββββββββββββββΆ Glue Studio
Existing Airflow DAGs? βββββββΆ MWAA
AWS-native orchestration? ββββΆ Step Functions
Stream processing windowed? ββΆ Managed Service for Apache Flink
"How do I query this?"¶
Ad-hoc SQL on S3? βββββββββββΆ Athena
BI dashboards? ββββββββββββββΆ QuickSight
Heavy MPP analytics? ββββββββΆ Redshift
Search / aggregations? ββββββΆ OpenSearch
Single-row key lookup? ββββββΆ DynamoDB
Federated SQL? ββββββββββββββΆ Athena federated query or Redshift federated query
These flowcharts cover at least 50% of likely exam scenario questions. Combine with the security stack from 05-security-governance.md and you have answers for ~70% of the exam.