Microscaled Spotify Security Architecture & Terraform IaC hosted on AWS
CompleteThe 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.
System Design
The architecture was derived from a first-principles capacity planning exercise before any infrastructure was provisioned.
Capacity Planning
| Dimension | Estimate | Rationale |
|---|---|---|
| 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 formats | Ogg/AAC at 64, 128, 320 kbps | Adaptive 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
| Method | Endpoint | Description |
|---|---|---|
GET | /search?q={query}&type=song,artist&limit=20&offset=0 | Search content types with pagination |
GET | /songs/trending?genre={genre}&limit=50 | Trending songs, optionally filtered by genre |
GET | /artists/{id}/songs?limit=50 | All songs by a specific artist |
Content Access
| Method | Endpoint | Description |
|---|---|---|
GET | /songs/{id} | Song metadata and presigned streaming URL |
GET | /songs/{id}/stream | Direct streaming endpoint (alternative to presigned URLs) |
GET | /playlists/{id}?include_songs=true | Playlist details with optional song list |
User Actions
| Method | Endpoint | Description |
|---|---|---|
POST | /playlists | Create a new playlist (name, is_public) |
PUT | /playlists/{id}/songs | Add songs to a playlist by ID array with position |
DELETE | /playlists/{id}/songs/{song_id} | Remove a song from a playlist |
POST | /songs/{id}/like | Like or unlike a song (toggle) |
GET | /users/me/playlists | Current user’s playlists |
GET | /users/me/liked-songs?limit=50&offset=0 | Songs 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.
| Table | Key Columns | Purpose |
|---|---|---|
songs | id, title, artist_id, duration_ms, s3_key, format, bitrate | Audio metadata and S3 object references |
users | id, cognito_sub, display_name, created_at | User profiles linked to Cognito identity |
artists | id, name, bio, image_url | Artist profiles |
playlists | id, user_id, name, is_public, created_at | User-created playlists |
playlist_songs | playlist_id, song_id, position | Ordered song membership in playlists |
user_likes | user_id, song_id, liked_at | Like/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
| Layer | Control | Scope |
|---|---|---|
| VPC | Custom 10.0.0.0/16 with public subnet | Network isolation |
| Security Group | SSH to admin IP/32 only, PostgreSQL to VPC CIDR only | Port-level access control |
| CloudFront | HTTPS enforced, default certificate | Transit encryption |
| S3 Bucket Policy | Deny unencrypted uploads, deny HTTP transport | Data protection |
| S3 Block Public Access | All four settings enabled | Access 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
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.
| Module | Resources | What It Provisions |
|---|---|---|
vpc | 11 | VPC, IGW, subnet, route table, security group with 6 rules |
ec2 | 2 | t3.micro with encrypted gp3 EBS, Elastic IP |
s3 | 10 | Audio bucket (versioned, encrypted, CORS, lifecycle, policy) + frontend bucket |
cloudfront | 3 | Dual-origin distribution with OAC, S3 bucket policy |
cognito | 3 | User pool with MFA, 2 app clients (public + confidential) |
monitoring | 6 | SNS 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
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
| Area | Demonstrated Capability |
|---|---|
| IAM | Custom policies with resource ARNs, permission boundaries, explicit deny guardrails, IAM evaluation logic, 5 role-based groups, instance profiles, trust policies |
| Networking | Custom VPC, subnet segmentation, security group rules with root cause for each port, VPC-only database access |
| Encryption | SSE-S3 at rest, TLS 1.2+ in transit, encrypted EBS, presigned URL time-limited access model |
| Compliance | 18 NIST 800-53 controls, 9 CIS benchmarks, AWS Config continuous compliance, simulated incident postmortem |
| IaC | 6 Terraform modules (37 resources), 2 CloudFormation comparison templates, environment separation, state management |
| Monitoring | CloudTrail (multi-region + validation), GuardDuty, Config rules, Access Analyzer, CloudWatch billing/CPU alarms, SNS alerting |
| Cost | Line-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.