AWS (Amazon Web Services) is the world's largest cloud platform — the foundation of a meaningful fraction of the internet. It's also the platform that's most associated with "I accidentally spent $5,000 in a weekend." Both characterizations are true. This post is a working developer's tour of what's actually in AWS, what matters for small-to-mid scale projects, and how to use it without an unpleasant credit-card surprise.
What AWS is
AWS is a catalog of around 200 distinct services covering compute, storage, networking, databases, AI, identity, observability, content delivery, and dozens of niches. You pick the services you need, glue them together, and pay for what you use.
The platform launched in 2006 with S3 (object storage) and EC2 (virtual machines). It's now the largest single business unit within Amazon by profit, and the platform of choice for enterprise workloads worldwide. Microsoft Azure and Google Cloud are competitive at the high end; AWS leads on service breadth and ecosystem maturity.
Why AWS is confusing
Three reasons people bounce off AWS:
- Service sprawl. ~200 services, many overlapping, many with cryptic names (RDS, ECS, EKS, ECR, EMR, EFS). You're never sure which one is "the right one."
- Pricing complexity. Many services have several pricing dimensions (compute time + data transfer + storage + requests + cross-region). The bill is hard to model upfront.
- IAM (Identity & Access Management). Granular, powerful, deeply confusing. The "principle of least privilege" is correct security; getting it right takes practice.
The trick to AWS is not learning all of it. The trick is identifying the 8-10 services you actually need and ignoring the rest until proven otherwise.
The services you actually need to know
- EC2 — virtual machines. The classic "give me a Linux server" service.
- Lambda — serverless functions. Upload code, run on demand, scale to zero.
- ECS / Fargate — container orchestration. Run Docker containers without managing servers (Fargate is the serverless container runtime).
- App Runner — PaaS-style "give me code, get a URL" service. Closest AWS analogue to Railway.
- S3 — object storage. Store files at any volume, cheaply.
- CloudFront — CDN. Cache static assets at edge locations near users.
- RDS — managed relational databases (PostgreSQL, MySQL, Aurora).
- DynamoDB — managed NoSQL key-value store.
- API Gateway — HTTP front door that routes to Lambda / other backends.
- SES — email sending.
- SNS / SQS — pub/sub and queues.
- CloudWatch — logs, metrics, alarms.
- IAM — permissions.
- Route 53 — DNS.
- Bedrock — managed access to LLMs including Claude (more below).
- Cognito — user authentication.
That's 16 services covering what most serious production workloads need. The other 180+ are for specialized situations.
Compute options compared
"Where does my code run?" has many answers on AWS:
- EC2 — rent a virtual machine, do everything yourself. Maximum control, maximum work, lowest unit cost. Use when you need specific hardware or full OS control.
- Lambda — upload functions, pay per execution. Cold-start latency. 15-minute max execution. Best for event-driven workloads, lightweight APIs, scheduled jobs.
- Fargate (via ECS or EKS) — containers without managing servers. Good middle ground between Lambda and EC2.
- App Runner — Railway-style PaaS. Simpler than Fargate but less flexible. Good for straightforward web apps.
- Lightsail — flat-rate VPS-style hosting. Predictable pricing, less feature-rich. Good for hobby projects.
- Beanstalk — older PaaS, still maintained, often bypassed in favor of newer options.
For a solo-dev iOS backend on AWS: Lambda + API Gateway for the API endpoints, or App Runner for a more traditional always-on server. Avoid spinning up EC2 manually unless you have a specific reason.
Storage and databases
S3
Object storage. Drop files in, retrieve them later. Used for: app file uploads, static website assets, backup, ML training data, log archives. Priced per GB stored + per request + per GB transferred out. The transfer-out part is where bills get surprising at scale.
RDS
Managed relational databases. AWS runs your PostgreSQL or MySQL instance, handles backups, patching, replication. Costs are dominated by instance size + storage + I/O.
Aurora
AWS's own MySQL/Postgres-compatible database engine. Faster than vanilla RDS, more expensive. Aurora Serverless v2 scales compute down to near-zero when idle, useful for variable workloads.
DynamoDB
Key-value / document database. Massive scale, predictable single-digit-millisecond latency, pay-per-request pricing available. Steep learning curve if you've only used relational databases — DynamoDB requires you to design access patterns up front.
EFS / EBS
File systems for EC2 instances. EBS = block storage attached to a single instance. EFS = network file system shared across instances. Mostly irrelevant if you're not running EC2.
What to pick
For most apps: PostgreSQL on RDS (or Aurora Serverless v2) + S3 for uploads. DynamoDB only when you have specific scale or access-pattern requirements. Aurora over RDS when the cost difference is justified by performance.
Networking essentials
The minimum networking concepts:
- VPC (Virtual Private Cloud) — a private network within AWS. Your resources live inside VPCs.
- Subnet — a slice of a VPC, scoped to a single Availability Zone.
- Security Group — firewall rules for an EC2 instance / RDS / etc.
- Internet Gateway — how resources in a VPC reach the public internet.
- NAT Gateway — outbound-only internet access for private subnets. Expensive (~$32/month + data charges).
- Route 53 — AWS's DNS service.
- CloudFront — CDN edge network.
The NAT Gateway is famously where small-team AWS bills surprise people. If you don't need outbound-only private subnets, don't deploy one.
IAM — security that scales
IAM (Identity and Access Management) controls who can do what. Three core entities:
- Users — humans with login credentials.
- Roles — sets of permissions that other services (EC2, Lambda) assume to perform actions.
- Policies — the actual rule documents that grant specific permissions.
Get the basics right early:
- Enable MFA on your root account. Never use the root account for daily work.
- Create a personal admin IAM user with MFA, use that.
- Give each service a specific role with the minimum permissions it needs. "AdministratorAccess" on a Lambda function is a footgun.
- Rotate access keys quarterly.
- Use IAM Access Analyzer to find overly-permissive policies.
Bedrock and Claude on AWS
AWS Bedrock is the managed service for accessing large language models, including Anthropic's Claude family, directly through AWS. The Bedrock API gives you Claude (and other models) with AWS billing, AWS-native authentication, and easy integration with other AWS services (Lambda, Step Functions, etc.).
Why use Bedrock vs the Anthropic API directly:
- Single bill. Your AWS bill includes the Claude usage.
- IAM-based auth rather than API keys. Easier permission management in larger orgs.
- VPC integration. Calls to Claude can stay inside AWS's private network.
- Compliance. Bedrock inherits AWS compliance certifications.
- Regional availability. Run inference in specific AWS regions.
Why use the Anthropic API directly instead:
- Newest models faster. Anthropic ships new Claude versions to their own API first; Bedrock typically follows.
- Some features Bedrock doesn't expose (prompt caching, certain beta features).
- Simpler setup if you're not otherwise an AWS shop.
For your iOS apps (which proxy through Railway), Anthropic API directly is the right call. Bedrock is for AWS-native architectures.
The cost traps that get everyone
The Greatest Hits of unexpected AWS bills:
- NAT Gateway egress. Every byte that flows out through a NAT Gateway is charged. Putting a busy Lambda behind a NAT instead of attaching it to public subnets can cost hundreds a month.
- S3 cross-region replication. Copying objects between regions adds storage + transfer cost.
- Data transfer out (to the internet, between regions, between AZs). Each is priced separately. AZ-to-AZ in the same region is usually a surprise.
- CloudWatch Logs retention. Default retention is "forever." Logs build up. Set retention to 30 or 90 days unless you need longer.
- Unused EBS volumes. Terminated EC2 instances sometimes leave EBS volumes behind. They keep billing.
- RDS snapshots. Old snapshots accumulate.
- Lambda timeout misconfigured. A Lambda set to 15-minute timeout that hangs in a loop costs full execution time per invocation.
- API Gateway requests at scale. Per-million-requests fees add up if you have a chatty API.
- Reserved Instances forgotten. RIs you bought for a workload you no longer run keep billing.
- Cross-account billing surprises. AWS Organizations consolidates bills; the surprise is when a sub-account spends $10k and you find out at month-end.
Mitigations: set a billing alarm on day one ("alert me if monthly spend crosses $50"). Use AWS Cost Explorer weekly. Tag every resource so you can attribute cost. Delete what you don't use.
When AWS is the right choice
AWS is the right choice when:
- You need services that simpler platforms don't offer (specific data-engineering tools, GPU instances, regulated-industry compliance, very large databases).
- You're already an AWS shop — sticking with one cloud is usually right.
- You have ops capacity (yourself with significant time, or a hire) to manage the complexity.
- You expect to scale beyond what PaaS platforms support.
- Your enterprise customers require AWS for compliance or procurement reasons.
AWS is the wrong first choice for a solo developer shipping an iOS app to the App Store. Railway / Vercel / Firebase will get you there faster with less risk. Migrate to AWS later if you outgrow the simpler platforms.
A pragmatic AWS starter stack
If you've decided AWS is right and want a minimal, sane setup:
- Compute: App Runner (simplest) or Lambda + API Gateway (most serverless).
- Database: Aurora Serverless v2 (Postgres). Scales to zero when idle.
- Storage: S3 for user-uploaded files. CloudFront in front of S3 for any public assets.
- DNS: Route 53.
- Email: SES.
- Auth: Cognito (or roll your own with a library — Cognito's quirks are real).
- Monitoring: CloudWatch + a third-party (Sentry, Datadog) for richer error tracking.
- Secrets: AWS Secrets Manager or Parameter Store.
- Billing alarm: set on day one.
That's enough to ship a real product. Add complexity only as specific problems require it.
See also: Backend Servers Explained, Railway vs AWS, Azure Deep Dive, GCP Deep Dive.
- AWS — Documentation
- AWS — Bedrock
- AWS — Pricing