AWS for Developers: The Services You Actually Need
I walk through the seven AWS services a full-stack developer reaches for on almost every project — EC2, Lambda, S3, RDS, CloudFront, IAM, and VPC — and explain when to use each one.

You open the AWS Management Console for the first time and the left sidebar has entries for services you’ve never heard of: satellite data reception, quantum computing workloads, hardware security module management. There are over 200 services in that panel. Most of them you’ll never touch.
A typical full-stack web application uses seven. Knowing which seven — and what each one is actually for — is the difference between navigating the console with confidence and clicking through panels hoping the right one appears.
I’ll walk through those seven services and explain when and why you’d reach for each one. This is part one of a two-part series. Part two uses these services together in a real deployment walkthrough.
On this page
- The seven services and what they cover
- EC2 and Lambda: two approaches to running code
- S3 and RDS: files and structured data go in different places
- CloudFront: the layer between users and your origin
- IAM and VPC: the foundation everything runs on
- Where developers run into trouble first
- Start with two services, then add the others
The seven services and what they cover
Here’s the short version before we go deeper:
| Service | Category | What it does |
|---|---|---|
| EC2 | Compute | A virtual machine you control and configure |
| Lambda | Compute | Code that runs in response to events, no server to manage |
| S3 | Storage | Object storage for files of any size or type |
| RDS | Database | A managed relational database (Postgres, MySQL, and others) |
| CloudFront | CDN | Caches and delivers content from edge locations globally |
| IAM | Security | Controls who and what can access your AWS resources |
| VPC | Networking | A private, isolated network your resources run inside |
Every application you deploy will use most of these. IAM and VPC work in the background after initial setup. EC2, S3, and RDS you’ll interact with on nearly every project. Lambda and CloudFront come in once your app outgrows its initial shape.
EC2 and Lambda: two approaches to running code
Amazon EC2 (Elastic Compute Cloud) gives you a virtual machine. You pick an instance type — which determines CPU, memory, and storage — choose an operating system, SSH in, and install whatever your application needs. The instance runs continuously, and you pay by the hour for as long as it’s on. If you’ve already built a REST API with Node.js and Express, EC2 is where that server runs in production. It’s also where you’d run a containerized application — EC2 supports Docker natively, so you can deploy the same image you built locally.
Lambda works differently. You write a handler function, upload it to AWS, and attach a trigger. When the trigger fires — an HTTP request arrives, a file lands in an S3 bucket, a message queues up — Lambda creates an execution environment, runs your code, and tears it down. You pay only for the time your function actually runs. Each invocation has a maximum duration of 15 minutes, which rules Lambda out for long-running processes.
The practical choice between them depends on the shape of your work:
- EC2 is for continuously running workloads: an API server, a WebSocket server, a background job processor that’s always polling. Anything that needs to hold state or run without waiting for a trigger.
- Lambda is for short-lived, event-driven tasks: resizing an uploaded image, sending a notification, running a scheduled export that fires once a night, processing a webhook payload.
Most applications end up using both — EC2 for the core server, Lambda for tasks that don’t justify keeping a process running around the clock.
Check this before moving on
- You understand why a long-running Express server belongs on EC2, not Lambda
- You know that Lambda runs only in response to a trigger — it’s not always-on
- You know the 15-minute invocation limit rules Lambda out for extended data migrations or batch jobs
S3 and RDS: files and structured data go in different places
Amazon S3 (Simple Storage Service) stores objects — files of any size, in any format — inside containers called buckets. Bucket names must be globally unique across all AWS accounts. You put user uploads, images, exported PDFs, frontend build artifacts, and database backups in S3. What you don’t put there is structured data you plan to query.
S3 has no query language. You retrieve objects by their key, which functions like a file path: uploads/user-42/avatar.jpg. The right pattern is to receive a file on your server, upload it to S3 from the backend, then store the key in your database. Serve the file from S3 or CloudFront — not from your application server’s disk.
Amazon RDS (Relational Database Service) runs a managed relational database on AWS-maintained infrastructure. You pick the engine — PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, or IBM Db2 — and AWS handles backups, software patching, automatic failure detection, and recovery. You still own schema design, query tuning, and application logic. AWS owns everything below that.
If you’ve been running PostgreSQL locally, the fundamentals carry over directly to RDS for PostgreSQL. The difference is you’re no longer responsible for the server it runs on.
RDS places your database in a private subnet inside a VPC, which means it’s unreachable from the public internet. You connect to it from your EC2 instances or Lambda functions within the same VPC — not from your laptop without a bastion host or VPN tunnel. That isolation is a feature, not a limitation.
The rule: files go to S3, structured relational data goes to RDS.
CloudFront: the layer between users and your origin
CloudFront is a content delivery network. It sits in front of your origin — an S3 bucket, an EC2 server, or a load balancer — and caches copies of your content at edge locations distributed globally. When a user requests a resource, CloudFront routes the request to the nearest edge location. If the content is already cached there, it returns immediately without reaching your origin server.
For most full-stack apps, CloudFront fills two roles:
Serving static assets from S3. Your compiled frontend bundle, images, and other static files live in an S3 bucket. CloudFront puts those assets in front of it, handles HTTPS certificates, and applies your custom domain. Users get faster load times; your S3 bucket receives fewer direct requests and stays private.
Adding HTTPS and caching to your API. Point CloudFront at your EC2 origin and it terminates TLS so your server doesn’t have to manage certificates itself. For routes that rarely change — like a public blog listing or a product catalogue — you can cache responses at the edge and reduce backend load.
One behaviour worth knowing: CloudFront fetches from your origin on the first request at each edge location. The cache fills over time. Static assets benefit immediately once cached; dynamic API responses require careful Cache-Control headers to avoid returning stale data.
IAM and VPC: the foundation everything runs on
AWS IAM (Identity and Access Management) controls what every identity on your account can do — and identities include services, not just people. When a Lambda function needs to read from an S3 bucket, it doesn’t use a username and password. You attach an IAM role to the Lambda function with explicit read permission on that specific bucket. The function assumes the role automatically at runtime.
That pattern — attaching IAM roles to AWS services rather than embedding credentials in environment variables — is the standard approach. Hardcoded access keys can leak in version control, in logs, or in memory dumps. An IAM role attached to a service has no long-term credentials to leak.
For account access: create an IAM user for your everyday development work with only the permissions that work requires. The AWS root account (the email and password you used when you signed up) should be reserved for account-level tasks only. IAM itself has no additional charge.
Amazon VPC (Virtual Private Cloud) provides the isolated virtual network your resources run inside. Every AWS region includes a default VPC, and it works immediately with no configuration needed for a first deployment. EC2 instances, RDS databases, and Lambda functions all run inside a VPC.
The key concept is public versus private subnets. A public subnet has a route to an internet gateway and can accept inbound connections from the internet. A private subnet does not — resources there can make outbound connections but aren’t directly reachable from outside. EC2 web servers go in public subnets. RDS databases go in private subnets. That separation is the primary boundary protecting your data.
Where developers run into trouble first
Running a database on EC2 instead of RDS. It’s possible to install PostgreSQL directly on an EC2 instance. You also become responsible for backups, patching, disk failure recovery, and replication. For most projects, a well-structured application with a managed database is the right foundation. Use RDS unless you have a specific reason to control the underlying machine.
Storing file uploads in the database. Binary data stored in database columns makes backups significantly larger, slows queries that scan table rows, and creates a transfer cost every time the file is retrieved. S3 exists for exactly this job. Keep the S3 object key in your database row, not the file itself.
Using the AWS root account for daily work. The root account has unrestricted access to everything, including billing and account deletion. If those credentials are exposed, the damage can be severe and fast. Create an IAM user with a defined permission set for development work.
Leaving internal services in public subnets. The default VPC places EC2 instances in public subnets, which is appropriate for web-facing servers. It’s not appropriate for your database, internal cache, or message queue. Put everything that doesn’t need to accept internet traffic in a private subnet.
Start with two services, then add the others
The natural starting point is EC2 and RDS — a server and a database. That pair runs most server-rendered apps and REST APIs without unnecessary complexity. Once you have file uploads or static assets to serve, add S3. Once you have an S3 bucket full of assets your users request repeatedly, add CloudFront in front of it.
IAM and VPC aren’t things you add later. They’re already present; you configure them as part of everything else. The defaults are fine for a first deployment. Get one principle right early: don’t work as root, and don’t put your database in a public subnet.
Lambda earns its place once you have tasks that don’t justify a continuously running process. A scheduled export that fires at midnight, an image resize triggered by an upload, a webhook handler that processes notifications — those are Lambda’s natural territory. If you find yourself running an EC2 instance just to execute a small function once an hour, that’s the signal to move it.
Understanding what each of these seven services does and where it sits in a typical deployment is enough to start reading architecture diagrams, making infrastructure decisions, and working through part two of this series.