Microscaled Spotify Security Architecture & Terraform IaC hosted on AWS

Complete
Cloud Security Engineer Simulation March 2026

The Problem

Cloud security portfolios suffer from a credibility gap. Listing “AWS IAM” or “Terraform” on a resume says nothing about whether you can design least-privilege policies, reason about IAM evaluation logic, or structure Terraform modules that a team can maintain.

This project closes that gap. It takes a well-known system design (Spotify’s audio streaming architecture), deploys a microscaled version on AWS, and wraps it in enterprise-grade security controls, all verifiable through the public GitHub repository, Terraform state, and this documentation.

What Was Built

A functional Spotify-inspired backend serving 28 audio tracks to 50 simulated users, deployed across 7 AWS services and managed by 37 Terraform resources. The infrastructure was designed, deployed, operated, documented, and decommissioned over a 4-day build cycle.

AWS Cloud – us-east-1 User React SPA CloudFront CDN + HTTPS EC2 t3.micro Node.js API PostgreSQL 16 JWT validation S3 Audio SSE-S3, versioned S3 Frontend Static hosting (OAC) Cognito User pool + MFA CloudWatch Alarms + Budget Security CloudTrail GuardDuty Config (4 rules) HTTPS /api/* Presigned URLs OAC JWT verify Metrics

System Design

The architecture was derived from a first-principles capacity planning exercise before any infrastructure was provisioned.

Capacity Planning

DimensionEstimateRationale
Audio storage~300 MB raw (100 songs × 3 MB avg at 128 kbps)Excludes cross-region replicas and versioning overhead; budget multiplier 2–3× for future headroom
Song metadata~10 KB (100 bytes × 100 songs)Title, artist references, duration, file URLs, format metadata
User metadata~50 KB (1 KB × 50 users)Profiles, preferences, playlist associations
Daily egress~2–3 GB (50 users × 10–15 streams × 3–4 MB each)Average listening session: 3.5 min at 128–160 kbps per stream
Audio formatsOgg/AAC at 64, 128, 320 kbpsAdaptive bitrate tiers: mobile data-saving, standard, premium

Architecture Rationale

The high-level design follows a standard three-tier pattern adapted for audio delivery:

  • Load balancing: Round-robin or least-connections distribution across API servers with health checks for high availability. At microscale, a single EC2 instance handles all traffic; the design documents the scaling path.
  • API servers: RESTful endpoints using JWT tokens to authenticate requests, query song metadata, and generate presigned URLs for audio content.
  • SQL database: PostgreSQL stores song metadata, user profiles, playlist relationships, and streaming URLs. Self-hosted on EC2 to stay within the $10/month budget constraint.
  • Blob storage (S3): All audio files stored in S3 with server-side encryption, versioning, and lifecycle policies. Presigned URLs provide time-limited access without exposing the bucket publicly.

API Design

The application exposes a RESTful API organized by domain. All endpoints require JWT authentication via Cognito.

Search & Discovery

MethodEndpointDescription
GET/search?q={query}&type=song,artist&limit=20&offset=0Search content types with pagination
GET/songs/trending?genre={genre}&limit=50Trending songs, optionally filtered by genre
GET/artists/{id}/songs?limit=50All songs by a specific artist

Content Access

MethodEndpointDescription
GET/songs/{id}Song metadata and presigned streaming URL
GET/songs/{id}/streamDirect streaming endpoint (alternative to presigned URLs)
GET/playlists/{id}?include_songs=truePlaylist details with optional song list

User Actions

MethodEndpointDescription
POST/playlistsCreate a new playlist (name, is_public)
PUT/playlists/{id}/songsAdd songs to a playlist by ID array with position
DELETE/playlists/{id}/songs/{song_id}Remove a song from a playlist
POST/songs/{id}/likeLike or unlike a song (toggle)
GET/users/me/playlistsCurrent user’s playlists
GET/users/me/liked-songs?limit=50&offset=0Songs liked by the current user
POST/users/me/follow/{artist_id}Follow an artist

Data Model

The relational schema uses PostgreSQL 16 with four core tables and two junction tables for many-to-many relationships.

TableKey ColumnsPurpose
songsid, title, artist_id, duration_ms, s3_key, format, bitrateAudio metadata and S3 object references
usersid, cognito_sub, display_name, created_atUser profiles linked to Cognito identity
artistsid, name, bio, image_urlArtist profiles
playlistsid, user_id, name, is_public, created_atUser-created playlists
playlist_songsplaylist_id, song_id, positionOrdered song membership in playlists
user_likesuser_id, song_id, liked_atLike/unlike tracking with timestamps

All tables use UUID primary keys. Foreign keys enforce referential integrity. The songs.s3_key field maps directly to the S3 object used for presigned URL generation.

Security Architecture: The Core of This Project

This is not a music streaming app that happens to have security. It is a security architecture that uses music streaming as the demonstration context.

IAM Design

Five IAM groups model enterprise job functions (Admin, Developer, DevOps, Security Auditor, Read-Only). Each has a custom policy scoped to specific resource ARNs, with no "Resource": "*" on sensitive actions.

The EC2 instance role uses a permission boundary as a privilege ceiling. The boundary is region-locked to us-east-1 and explicitly denies organizations:*, account:*, and user lifecycle actions. This means even if AdministratorAccess were attached to the role, it could not create IAM users, modify the account, or provision resources outside us-east-1.

IAM policy evaluation follows a deterministic chain: Explicit Deny beats Explicit Allow beats Implicit Deny. The Security Auditor role demonstrates this with a broad iam:Get* Allow paired with an explicit iam:Create*, iam:Delete*, iam:Update* Deny, meaning read everything, change nothing, override-proof.

Network Controls

LayerControlScope
VPCCustom 10.0.0.0/16 with public subnetNetwork isolation
Security GroupSSH to admin IP/32 only, PostgreSQL to VPC CIDR onlyPort-level access control
CloudFrontHTTPS enforced, default certificateTransit encryption
S3 Bucket PolicyDeny unencrypted uploads, deny HTTP transportData protection
S3 Block Public AccessAll four settings enabledAccess prevention

S3 Presigned URL Security

Audio files are served via 15-minute presigned URLs generated by the EC2 instance role. The URL is bound to a specific S3 object key, inherits the signer’s IAM permissions, and becomes invalid after expiry. The S3 bucket has no public access; presigned URLs are the only path to audio content.

Detective Controls

CloudTrail Multi-region Log validation GuardDuty Threat detection 15-min publish AWS Config 4 compliance rules Continuous eval Access Analyzer External access Policy findings CloudWatch Billing $10/$20 CPU 80% alarm

Infrastructure as Code

All infrastructure is defined in Terraform 1.14.7 with the AWS provider v5.100.0. Six reusable modules, 37 managed resources, environment-separated configurations.

ModuleResourcesWhat It Provisions
vpc11VPC, IGW, subnet, route table, security group with 6 rules
ec22t3.micro with encrypted gp3 EBS, Elastic IP
s310Audio bucket (versioned, encrypted, CORS, lifecycle, policy) + frontend bucket
cloudfront3Dual-origin distribution with OAC, S3 bucket policy
cognito3User pool with MFA, 2 app clients (public + confidential)
monitoring6SNS topic, AWS Budget, 3 CloudWatch alarms

Two supplementary CloudFormation templates (VPC and S3) are included in the repository for IaC tool comparison, with a side-by-side analysis of state management, rollback behavior, and drift detection differences.

Compliance Posture

The project maps to 18 NIST 800-53 controls and 9 CIS AWS Foundations Benchmark v3.0 controls. Full mapping tables are in the GRC documentation.

Key compliance areas demonstrated: Account management (AC-2), Least privilege (AC-6), Audit events (AU-2), Continuous monitoring (CA-7), Boundary protection (SC-7), Transmission confidentiality (SC-8), Information at rest (SC-28).

Incident Response

A simulated postmortem documents an S3 Block Public Access misconfiguration caused by a Terraform resource deletion. The report follows standard incident response format: timeline, root cause analysis, blast radius assessment, remediation actions, and preventive measures. Defense-in-depth controls limited actual exposure to zero.

Cost Architecture

EC2 t3.micro $7.59 EBS 20GB gp3 $1.60 S3 + requests $0.06 CloudFront $0.00 (1TB free) Cognito $0.00 (50K MAU free) $10 budget Total ~$9.25/month

Every architectural tradeoff in this project is cost-driven and documented: self-hosted PostgreSQL over RDS (saves $12.41/mo), no NAT Gateway (saves $32.40/mo), no WAF (saves $5/mo), PriceClass_100 on CloudFront (cheapest edge distribution). Budget alarms trigger at 80%, 100%, and 150% of the $10 cap.

Build Process and Debugging

The project was built over 4 days with 3,929 terminal commands logged. A 27-entry debugging journal documents every issue encountered, from WSL path resolution failures to PostgreSQL pg_hba.conf rule ordering, IAM ARN formatting, and Terraform lifecycle management. Each entry includes what happened, why, how it was fixed, and the lesson extracted.

Recurring themes: path discrepancies between Windows and WSL filesystems (8+ occurrences), order-of-operations dependencies in AWS service configuration, and the gap between knowing a concept and correctly implementing it in CLI syntax.

Technical Depth Indicators

AreaDemonstrated Capability
IAMCustom policies with resource ARNs, permission boundaries, explicit deny guardrails, IAM evaluation logic, 5 role-based groups, instance profiles, trust policies
NetworkingCustom VPC, subnet segmentation, security group rules with root cause for each port, VPC-only database access
EncryptionSSE-S3 at rest, TLS 1.2+ in transit, encrypted EBS, presigned URL time-limited access model
Compliance18 NIST 800-53 controls, 9 CIS benchmarks, AWS Config continuous compliance, simulated incident postmortem
IaC6 Terraform modules (37 resources), 2 CloudFormation comparison templates, environment separation, state management
MonitoringCloudTrail (multi-region + validation), GuardDuty, Config rules, Access Analyzer, CloudWatch billing/CPU alarms, SNS alerting
CostLine-item breakdown, optimization decisions documented with exact thresholds, budget automation

Repository

GitHub: aws-spotify – Full source: Terraform modules, IAM policies, CloudFormation templates, API server, React frontend, GRC documentation, postmortem, debugging journal.

Runbook: AWS_Spotify_Runbook_v3.pdf – Security architecture documentation with IAM evaluation logic, presigned URL security model, VPC segmentation rationale, compliance mappings, and Terraform module reference.

Design Document: HighLevelOverview.pdf – System design framework with capacity planning, API design, data model, and architecture rationale.