Amazon Web Services (AWS) is the world's largest cloud platform, powering millions of companies from Netflix and Airbnb to NASA. Learning AWS opens doors to DevOps, backend, cloud architect, and SRE roles — and the free tier gives you enough resources to learn without paying a cent. This tutorial takes you from zero to deploying real infrastructure, step by step.
What you'll learn
| Topic | What you'll be able to do |
|---|---|
| Setup | Create a free AWS account and configure the CLI |
| IAM | Manage users, roles, and permissions securely |
| EC2 | Launch, connect to, and manage virtual servers |
| S3 | Store and serve files at massive scale |
| RDS | Run managed relational databases |
| Lambda | Run code without managing servers |
| VPC | Build isolated network environments |
| CloudWatch | Monitor and alert on your infrastructure |
| Deployment | Build a real 3-tier web app on AWS |
AWS vs other cloud providers
| Feature | AWS | Azure | Google Cloud |
|---|---|---|---|
| Market share | ~32% | ~22% | ~12% |
| Services | 200+ | 200+ | 150+ |
| Best for | Broadest ecosystem | Microsoft/enterprise | Data/ML |
| Free tier | 12 months + always free | 12 months + always free | $300 credit |
| Certifications | CCP, SAA, SAP, etc. | AZ-900, AZ-104, etc. | ACE, PCE, etc. |
| Job market | Most jobs | #2 | #3 |
| Learning curve | Steep (most services) | Moderate | Moderate |
1. Setting up AWS
Create a free account
- Go to aws.amazon.com and click Create a Free Account
- Enter email, choose account name, set password
- Enter payment info (required, but free tier won't charge you)
- Verify phone number
- Select Basic Support (free)
- Choose your nearest region (US East N. Virginia = most services available)
AWS Free Tier highlights
| Service | Free tier |
|---|---|
| EC2 | 750 hrs/mo t2.micro or t3.micro (12 months) |
| S3 | 5 GB storage, 20k GET, 2k PUT requests |
| RDS | 750 hrs/mo db.t3.micro (12 months) |
| Lambda | 1M requests/mo + 400k GB-seconds (always free) |
| CloudWatch | 10 custom metrics, 5 GB logs (always free) |
| DynamoDB | 25 GB storage, 25 RCU/WCU (always free) |
Install and configure AWS CLI
# macOS (Homebrew)
brew install awscli
# Windows (download installer from aws.amazon.com/cli)
# Or via winget:
winget install Amazon.AWSCLI
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Verify
aws --version
# aws-cli/2.x.x Python/3.x.x ...
Configure with your credentials (IAM user access key — we'll create one in the next section):
aws configure
# AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
# AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# Default region name [None]: us-east-1
# Default output format [None]: json
2. IAM — Identity and Access Management
IAM is how AWS controls who can do what to which resources. Get this wrong and you either lock yourself out or leave the account wide open.
Core IAM concepts
| Concept | What it is | Example |
|---|---|---|
| Root user | Account owner, all permissions | Only for billing and initial setup |
| IAM user | A person or app with credentials | alice@company.com |
| Group | Collection of users with shared permissions | developers, admins |
| Policy | JSON document defining permissions | AmazonS3FullAccess |
| Role | Temporary permissions assumed by services/users | EC2 role to read S3 |
| MFA | Multi-factor authentication | App-based TOTP |
Create your first IAM user (for daily work — never use root)
# In AWS console: IAM → Users → Add users
# Or via CLI (after root configures CLI):
# Create a user
aws iam create-user --user-name myuser
# Attach a policy
aws iam attach-user-policy \
--user-name myuser \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
# Create access keys for CLI
aws iam create-access-key --user-name myuser
Least-privilege policy example
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
}
]
}
IAM roles (for services)
Roles let AWS services (like EC2 or Lambda) access other services without embedding credentials:
# Create a role that EC2 can assume
aws iam create-role \
--role-name EC2-S3-ReadOnly \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
# Attach S3 read policy to the role
aws iam attach-role-policy \
--role-name EC2-S3-ReadOnly \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
IAM security best practices
- Enable MFA on root and all IAM users
- Never use root for daily work
- Grant least privilege — only what's needed
- Use roles for services, not access keys
- Rotate access keys every 90 days
- Use IAM Access Analyzer to find overly-permissive policies
3. EC2 — Elastic Compute Cloud
EC2 gives you virtual servers (called instances) in the cloud. You choose the OS, size, and configuration.
EC2 instance types
| Family | Use case | Example sizes |
|---|---|---|
| t3/t4g | General purpose, burstable (dev/test) | t3.micro, t3.small |
| m7i | Balanced CPU/memory (web servers) | m7i.large, m7i.xlarge |
| c7i | Compute-intensive (video encoding, HPC) | c7i.2xlarge |
| r7i | Memory-intensive (databases, caches) | r7i.4xlarge |
| p4d | GPU instances (ML training) | p4d.24xlarge |
| i4i | Storage-optimized (high I/O DBs) | i4i.large |
Launch your first EC2 instance (CLI)
# Find the latest Amazon Linux 2023 AMI
aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=al2023-ami-*-x86_64" \
--query "Images | sort_by(@, &CreationDate) | [-1].ImageId" \
--output text
# Create a key pair for SSH access
aws ec2 create-key-pair \
--key-name my-key \
--query "KeyMaterial" \
--output text > my-key.pem
chmod 400 my-key.pem
# Launch an instance
aws ec2 run-instances \
--image-id ami-0c02fb55956c7d316 \
--instance-type t3.micro \
--key-name my-key \
--count 1 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=my-server}]'
# Get the public IP
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=my-server" \
--query "Reservations[0].Instances[0].PublicIpAddress" \
--output text
# Connect via SSH
ssh -i my-key.pem ec2-user@<PUBLIC_IP>
Security Groups (EC2 firewall)
Security groups control inbound and outbound traffic to your instances:
# Create a security group
aws ec2 create-security-group \
--group-name web-sg \
--description "Web server security group"
# Allow SSH from your IP
aws ec2 authorize-security-group-ingress \
--group-name web-sg \
--protocol tcp \
--port 22 \
--cidr YOUR_IP/32
# Allow HTTP from anywhere
aws ec2 authorize-security-group-ingress \
--group-name web-sg \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
# Allow HTTPS from anywhere
aws ec2 authorize-security-group-ingress \
--group-name web-sg \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
Install a web server on EC2
# After SSHing into the instance:
sudo dnf update -y
sudo dnf install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# Your site is now live at http://PUBLIC_IP
EC2 pricing models
| Model | How it works | Best for | Savings |
|---|---|---|---|
| On-Demand | Pay per second, no commitment | Dev, unpredictable load | — |
| Reserved | 1 or 3 year commitment | Steady baseline load | Up to 72% |
| Spot | Use unused AWS capacity | Batch, fault-tolerant | Up to 90% |
| Savings Plans | Flexible commitment by $/hr | Mix of instance types | Up to 66% |
| Dedicated Hosts | Physical server for you | Compliance | Varies |
4. S3 — Simple Storage Service
S3 stores any file at virtually unlimited scale. It's object storage — not a file system.
Core S3 concepts
| Concept | What it is |
|---|---|
| Bucket | Top-level container (globally unique name) |
| Object | A file + metadata stored in a bucket |
| Key | The object's full path (e.g. images/cat.jpg) |
| Prefix | Folder-like grouping (not real folders) |
| ACL | Access control list for bucket/object |
| Versioning | Keep multiple versions of objects |
Create a bucket and upload files
# Create a bucket (name must be globally unique)
aws s3 mb s3://my-unique-bucket-name-2025
# Upload a single file
aws s3 cp ./photo.jpg s3://my-unique-bucket-name-2025/
# Upload an entire folder
aws s3 sync ./my-folder s3://my-unique-bucket-name-2025/my-folder/
# List bucket contents
aws s3 ls s3://my-unique-bucket-name-2025/
# Download a file
aws s3 cp s3://my-unique-bucket-name-2025/photo.jpg ./downloaded.jpg
# Delete an object
aws s3 rm s3://my-unique-bucket-name-2025/photo.jpg
# Delete a bucket and all contents
aws s3 rb s3://my-unique-bucket-name-2025 --force
Host a static website on S3
# Enable static website hosting
aws s3 website s3://my-site-bucket/ \
--index-document index.html \
--error-document error.html
# Make objects publicly readable (bucket policy)
aws s3api put-bucket-policy \
--bucket my-site-bucket \
--policy '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-site-bucket/*"
}]
}'
# Upload your site
aws s3 sync ./dist s3://my-site-bucket/
# URL format: http://my-site-bucket.s3-website-us-east-1.amazonaws.com
S3 storage classes
| Class | Use case | Retrieval | Cost |
|---|---|---|---|
| Standard | Frequently accessed data | Instant | High |
| Standard-IA | Infrequent access | Instant | Medium |
| One Zone-IA | Infrequent, single AZ | Instant | Lower |
| Glacier Instant | Archive, rare access | Instant | Low |
| Glacier Flexible | Archive, occasional | Minutes–hours | Very low |
| Glacier Deep Archive | Long-term archive | Hours | Lowest |
| Intelligent-Tiering | Unknown access pattern | Instant | Auto |
Lifecycle rules (auto-archive old objects)
{
"Rules": [
{
"ID": "archive-old-logs",
"Status": "Enabled",
"Filter": {"Prefix": "logs/"},
"Transitions": [
{"Days": 30, "StorageClass": "STANDARD_IA"},
{"Days": 90, "StorageClass": "GLACIER"}
],
"Expiration": {"Days": 365}
}
]
}
5. RDS — Relational Database Service
RDS runs managed databases so you don't have to patch, backup, or set up replication yourself.
Supported database engines
| Engine | Best for |
|---|---|
| MySQL | Web apps, WordPress |
| PostgreSQL | Advanced SQL features, JSON, extensions |
| MariaDB | MySQL-compatible, open-source |
| SQL Server | Windows/.NET applications |
| Oracle | Enterprise legacy systems |
| Aurora MySQL | MySQL-compatible, 5× faster |
| Aurora PostgreSQL | PostgreSQL-compatible, 3× faster |
Create a PostgreSQL RDS instance
# Create a subnet group first
aws rds create-db-subnet-group \
--db-subnet-group-name my-db-subnet \
--db-subnet-group-description "My DB subnet group" \
--subnet-ids subnet-abc123 subnet-def456
# Launch an RDS instance (free tier eligible)
aws rds create-db-instance \
--db-instance-identifier my-postgres \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version "15.4" \
--master-username admin \
--master-user-password MyPassword123! \
--allocated-storage 20 \
--no-publicly-accessible \
--db-subnet-group-name my-db-subnet \
--backup-retention-period 7
# Check status
aws rds describe-db-instances \
--db-instance-identifier my-postgres \
--query "DBInstances[0].DBInstanceStatus"
Connect to RDS from EC2
# Get the endpoint
aws rds describe-db-instances \
--db-instance-identifier my-postgres \
--query "DBInstances[0].Endpoint.Address" \
--output text
# Connect with psql (on EC2 in same VPC)
psql -h <ENDPOINT> -U admin -d postgres
# From Python application
import psycopg2
conn = psycopg2.connect(
host="my-postgres.xxxx.us-east-1.rds.amazonaws.com",
database="mydb",
user="admin",
password="MyPassword123!"
)
RDS key features
| Feature | What it does |
|---|---|
| Multi-AZ | Automatic failover to standby in another AZ |
| Read Replicas | Scale reads across multiple replicas |
| Automated backups | Daily snapshots, point-in-time recovery |
| Encryption | AES-256 at rest, TLS in transit |
| Performance Insights | Query-level performance monitoring |
| Enhanced Monitoring | OS-level metrics every second |
6. Lambda — Serverless Functions
Lambda runs your code in response to events without you managing any servers. You pay only for execution time.
Lambda basics
| Concept | Detail |
|---|---|
| Function | Your code + configuration |
| Handler | Entry point (e.g. lambda_function.lambda_handler) |
| Event | JSON input that triggers the function |
| Runtime | Python 3.12, Node.js 20, Java 21, Go, etc. |
| Memory | 128 MB to 10 GB |
| Timeout | Max 15 minutes |
| Invocation | Synchronous (API GW) or async (S3, SQS) |
Your first Lambda function
# lambda_function.py
import json
def lambda_handler(event, context):
name = event.get("name", "World")
return {
"statusCode": 200,
"body": json.dumps({"message": f"Hello, {name}!"})
}
Deploy via CLI:
# Package the function
zip function.zip lambda_function.py
# Create the function
aws lambda create-function \
--function-name hello-world \
--runtime python3.12 \
--zip-file fileb://function.zip \
--handler lambda_function.lambda_handler \
--role arn:aws:iam::ACCOUNT_ID:role/lambda-basic-role
# Invoke it
aws lambda invoke \
--function-name hello-world \
--payload '{"name": "AWS"}' \
response.json
cat response.json
# {"statusCode": 200, "body": "{\"message\": \"Hello, AWS!\"}"}
Lambda triggers
| Trigger | Use case |
|---|---|
| API Gateway / Function URL | HTTP endpoints |
| S3 | Process uploads (resize images, parse CSVs) |
| SQS | Process queued messages |
| EventBridge | Scheduled tasks (cron) |
| DynamoDB Streams | React to DB changes |
| SNS | Fan-out notifications |
| Cognito | Custom auth flows |
S3-triggered Lambda (resize images on upload)
import boto3
from PIL import Image
import io
s3 = boto3.client('s3')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
# Download original
response = s3.get_object(Bucket=bucket, Key=key)
image_data = response['Body'].read()
# Resize
image = Image.open(io.BytesIO(image_data))
image.thumbnail((800, 800))
# Save resized version
buffer = io.BytesIO()
image.save(buffer, format='JPEG')
buffer.seek(0)
# Upload to thumbnails bucket
s3.put_object(
Bucket='my-thumbnails',
Key=key,
Body=buffer,
ContentType='image/jpeg'
)
return {'statusCode': 200}
7. VPC — Virtual Private Cloud
A VPC is your own isolated network inside AWS. All other services run inside a VPC.
VPC components
| Component | What it is |
|---|---|
| VPC | Your private network (CIDR e.g. 10.0.0.0/16) |
| Subnet | Subdivision of a VPC (public or private) |
| Internet Gateway | Connects VPC to the internet |
| NAT Gateway | Lets private subnets reach the internet (not vice versa) |
| Route Table | Rules for directing network traffic |
| Security Group | Stateful instance-level firewall |
| NACL | Stateless subnet-level firewall |
| VPC Peering | Connect two VPCs together |
| Endpoint | Private connection to AWS services (no internet) |
Security Group vs NACL
| Feature | Security Group | NACL |
|---|---|---|
| Level | Instance | Subnet |
| State | Stateful | Stateless |
| Rules | Allow only | Allow and deny |
| Evaluation | All rules evaluated | Rules evaluated in order (lowest number first) |
| Default | Deny all in, allow all out | Allow all in and out |
| Use case | Primary firewall | Subnet-level blocking |
Create a VPC with public and private subnets
# Create VPC
VPC_ID=$(aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--query "Vpc.VpcId" --output text)
aws ec2 create-tags \
--resources $VPC_ID \
--tags Key=Name,Value=my-vpc
# Create public subnet
PUBLIC_SUBNET=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a \
--query "Subnet.SubnetId" --output text)
# Create private subnet
PRIVATE_SUBNET=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--availability-zone us-east-1b \
--query "Subnet.SubnetId" --output text)
# Create and attach internet gateway
IGW=$(aws ec2 create-internet-gateway \
--query "InternetGateway.InternetGatewayId" --output text)
aws ec2 attach-internet-gateway \
--vpc-id $VPC_ID \
--internet-gateway-id $IGW
# Create route table for public subnet
RT=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query "RouteTable.RouteTableId" --output text)
aws ec2 create-route \
--route-table-id $RT \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id $IGW
aws ec2 associate-route-table \
--subnet-id $PUBLIC_SUBNET \
--route-table-id $RT
8. CloudWatch — Monitoring and Logging
CloudWatch collects metrics, logs, and events from your AWS resources.
Key CloudWatch features
| Feature | Use case |
|---|---|
| Metrics | CPU, memory, request count, latency |
| Alarms | Alert when metric crosses threshold |
| Logs | Collect and search log streams |
| Log Insights | Query logs with SQL-like syntax |
| Dashboards | Custom metrics dashboards |
| Events / EventBridge | Trigger actions on schedule or events |
| Synthetics | Synthetic canary monitoring |
Create an alarm for EC2 CPU
aws cloudwatch put-metric-alarm \
--alarm-name "high-cpu" \
--alarm-description "CPU above 80%" \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2 \
--dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
--alarm-actions arn:aws:sns:us-east-1:ACCOUNT:my-topic
Query CloudWatch Logs with Log Insights
-- Find all 5xx errors in the last hour
fields @timestamp, @message
| filter @message like /5[0-9][0-9]/
| sort @timestamp desc
| limit 100
-- Count errors by minute
fields @timestamp
| filter @message like /ERROR/
| stats count() as errors by bin(1m)
| sort @timestamp desc
-- Find slowest Lambda executions
fields @timestamp, @duration, @requestId
| filter @type = "REPORT"
| sort @duration desc
| limit 20
9. Project: Deploy a 3-Tier Web App on AWS
Let's put it all together — a Node.js API + PostgreSQL + S3 for static assets.
Architecture
Internet
│
▼
[CloudFront] ──── [S3 Static Site]
│
▼
[Application Load Balancer] (public subnet)
│
▼
[EC2 Auto Scaling Group] (private subnet)
│
├── [RDS PostgreSQL] (private subnet)
└── [S3 Bucket] (via VPC Endpoint)
Step 1: Create the VPC
Use the VPC wizard in the console:
- VPC CIDR:
10.0.0.0/16 - 2 public subnets (for ALB):
10.0.1.0/24,10.0.2.0/24 - 2 private subnets (for EC2+RDS):
10.0.3.0/24,10.0.4.0/24 - Enable NAT Gateway in one public subnet
Step 2: Launch RDS in private subnet
aws rds create-db-instance \
--db-instance-identifier app-db \
--db-instance-class db.t3.micro \
--engine postgres \
--master-username appuser \
--master-user-password "SecurePass123!" \
--allocated-storage 20 \
--vpc-security-group-ids sg-rds-id \
--db-subnet-group-name my-private-db-subnet \
--no-publicly-accessible
Step 3: Create an EC2 launch template
cat > user-data.sh << 'EOF'
#!/bin/bash
dnf update -y
dnf install -y nodejs npm
npm install -g pm2
# Clone your app
git clone https://github.com/yourrepo/api.git /app
cd /app
npm install
pm2 start app.js --name api
pm2 startup systemd
pm2 save
EOF
aws ec2 create-launch-template \
--launch-template-name app-lt \
--launch-template-data '{
"ImageId": "ami-0c02fb55956c7d316",
"InstanceType": "t3.micro",
"IamInstanceProfile": {"Name": "app-instance-profile"},
"SecurityGroupIds": ["sg-app-id"],
"UserData": "'$(base64 -w0 user-data.sh)'"
}'
Step 4: Create Auto Scaling Group
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name app-asg \
--launch-template LaunchTemplateName=app-lt,Version='$Latest' \
--min-size 2 \
--max-size 10 \
--desired-capacity 2 \
--target-group-arns arn:aws:elasticloadbalancing:... \
--vpc-zone-identifier "subnet-private1,subnet-private2"
Step 5: Host frontend on S3 + CloudFront
# Build and deploy frontend
npm run build
aws s3 sync dist/ s3://my-app-frontend/
# Create CloudFront distribution pointing to S3
# (use console or CloudFormation for complex config)
10. Other Essential AWS Services
DynamoDB (NoSQL)
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('users')
# Put item
table.put_item(Item={
'user_id': 'u001',
'name': 'Alice',
'email': 'alice@example.com'
})
# Get item
response = table.get_item(Key={'user_id': 'u001'})
user = response['Item']
# Query (requires index on email)
response = table.query(
IndexName='email-index',
KeyConditionExpression='email = :email',
ExpressionAttributeValues={':email': 'alice@example.com'}
)
SQS (Message Queue)
import boto3
sqs = boto3.client('sqs')
queue_url = 'https://sqs.us-east-1.amazonaws.com/123456789012/my-queue'
# Send a message
sqs.send_message(
QueueUrl=queue_url,
MessageBody='{"job": "resize-image", "key": "uploads/photo.jpg"}'
)
# Receive and process messages
response = sqs.receive_message(
QueueUrl=queue_url,
MaxNumberOfMessages=10,
WaitTimeSeconds=20 # Long polling
)
for msg in response.get('Messages', []):
print(msg['Body'])
sqs.delete_message(
QueueUrl=queue_url,
ReceiptHandle=msg['ReceiptHandle']
)
SNS (Pub/Sub)
import boto3
sns = boto3.client('sns')
# Create a topic
topic = sns.create_topic(Name='alerts')
topic_arn = topic['TopicArn']
# Subscribe an email
sns.subscribe(
TopicArn=topic_arn,
Protocol='email',
Endpoint='admin@example.com'
)
# Publish a message
sns.publish(
TopicArn=topic_arn,
Message='High CPU alert on instance i-1234567890',
Subject='AWS Alert'
)
API Gateway
API Gateway turns Lambda functions into HTTP APIs:
# Create a REST API
aws apigateway create-rest-api --name my-api
# Or use HTTP API (simpler, cheaper)
aws apigatewayv2 create-api \
--name my-http-api \
--protocol-type HTTP \
--target arn:aws:lambda:us-east-1:ACCOUNT:function:my-function
AWS services quick reference
| Service | Category | What it does |
|---|---|---|
| EC2 | Compute | Virtual machines |
| ECS / EKS | Compute | Docker / Kubernetes managed |
| Lambda | Compute | Serverless functions |
| Fargate | Compute | Serverless containers |
| S3 | Storage | Object storage |
| EBS | Storage | Block storage for EC2 |
| EFS | Storage | Shared file system |
| RDS | Database | Managed relational DB |
| DynamoDB | Database | Managed NoSQL |
| ElastiCache | Database | Managed Redis/Memcached |
| VPC | Networking | Private network |
| Route 53 | Networking | DNS + health checks |
| CloudFront | Networking | CDN |
| ALB / NLB | Networking | Load balancers |
| IAM | Security | Identity + access management |
| KMS | Security | Key management |
| Secrets Manager | Security | Store and rotate secrets |
| CloudWatch | Monitoring | Metrics, logs, alarms |
| CloudTrail | Auditing | API call history |
| SQS | Messaging | Message queue |
| SNS | Messaging | Pub/sub notifications |
| EventBridge | Messaging | Event bus |
| CodePipeline | DevOps | CI/CD pipeline |
| CodeBuild | DevOps | Build service |
| CloudFormation | DevOps | Infrastructure as code |
| Cognito | Auth | User pools + identity |
AWS regions and availability zones
Region (e.g. us-east-1 / N. Virginia)
├── Availability Zone A (us-east-1a)
│ ├── Data Center 1
│ └── Data Center 2
├── Availability Zone B (us-east-1b)
│ └── Data Center 3
└── Availability Zone C (us-east-1c)
└── Data Center 4
| Region | Code | Notes |
|---|---|---|
| US East (N. Virginia) | us-east-1 | Cheapest, most services |
| US West (Oregon) | us-west-2 | Good West Coast option |
| EU (Ireland) | eu-west-1 | Popular for Europe |
| EU (Frankfurt) | eu-central-1 | GDPR-friendly |
| Asia Pacific (Singapore) | ap-southeast-1 | SEA/ANZ |
| Asia Pacific (Tokyo) | ap-northeast-1 | Japan |
Rule of thumb: Deploy in the region closest to your users. Use us-east-1 for learning (cheapest and most services).
AWS learning path
| Stage | Topics | Timeline |
|---|---|---|
| 1. Foundations | Console navigation, IAM, S3, EC2 basics | Week 1–2 |
| 2. Core services | RDS, Lambda, VPC, CloudWatch | Week 3–4 |
| 3. Application deployment | ALB, Auto Scaling, ECS/Fargate | Week 5–6 |
| 4. DevOps | CodePipeline, CloudFormation, Terraform | Week 7–8 |
| 5. Security & cost | KMS, WAF, Cost Explorer, Trusted Advisor | Week 9–10 |
| 6. Certification | AWS Cloud Practitioner (CCP) or SAA | Month 3 |
| 7. Specialisation | Databases / Machine Learning / Security path | Month 4–6 |
AWS Certification roadmap
| Cert | Code | Level | Who it's for |
|---|---|---|---|
| Cloud Practitioner | CLF-C02 | Foundational | Everyone starting AWS |
| Solutions Architect Associate | SAA-C03 | Associate | Architects, engineers |
| Developer Associate | DVA-C02 | Associate | Developers |
| SysOps Administrator | SOA-C02 | Associate | Ops/SRE |
| Solutions Architect Professional | SAP-C02 | Professional | Senior architects |
| DevOps Engineer Professional | DOP-C02 | Professional | DevOps engineers |
Common mistakes
| Mistake | Problem | Fix |
|---|---|---|
| Using root account for daily work | Full access compromise = game over | Create IAM user immediately |
| Public S3 buckets | Data breaches | Default deny, use signed URLs |
| Hardcoded AWS credentials | Keys leaked to GitHub | Use IAM roles, Secrets Manager |
| Single Availability Zone | One outage kills everything | Deploy to 2+ AZs |
| No VPC for databases | DB exposed to internet | RDS in private subnet only |
| Default security groups | Too permissive by default | Create custom security groups |
| No backups configured | Data loss is permanent | Enable automated backups on RDS |
| Not monitoring costs | Surprise bill at month end | Set billing alarms in CloudWatch |
AWS vs related terms
| Term | What it is |
|---|---|
| AWS | Amazon's cloud platform (the whole thing) |
| EC2 | Virtual machines on AWS |
| S3 | Object storage on AWS |
| IAM | Access control for AWS |
| VPC | Private network on AWS |
| CloudFormation | AWS-native Infrastructure as Code |
| Terraform | Open-source IaC that supports AWS (and others) |
| Kubernetes (EKS) | Container orchestration on AWS |
| Serverless | Lambda + API Gateway pattern |
| IaC | Code that defines infrastructure (CloudFormation, Terraform) |
| Azure | Microsoft's cloud platform (competitor to AWS) |
| GCP | Google's cloud platform (competitor to AWS) |
Frequently asked questions
Is AWS free to learn? Yes — the AWS Free Tier gives 12 months of free EC2 (t2.micro), S3, RDS and more. Set billing alarms immediately and keep resources small. Always terminate instances and delete data when done experimenting.
Which AWS services should I learn first? Start with IAM (security foundation), then S3 (simplest service), then EC2 (virtual machines). Once comfortable, add RDS and Lambda. Everything else builds on those five.
How long does it take to learn AWS? 2–4 weeks to get comfortable with core services. 2–3 months to pass the AWS Solutions Architect Associate exam. 6+ months to feel confident architecting production systems.
Do I need Linux knowledge for AWS? Yes — EC2 instances typically run Linux. Learn basic navigation, file management, and systemd before diving into EC2. You can also start with managed services (Lambda, RDS) to delay the Linux learning curve.
What's the difference between AWS regions and availability zones? A region is a geographic area (e.g. us-east-1 / North Virginia). Each region has 2–7 availability zones (AZs), which are separate data centres a few miles apart. Deploy across 2+ AZs for high availability — if one data centre fails, the other keeps running.
Should I use the AWS Console or CLI? Learn both. The console is great for exploring and understanding services visually. The CLI is essential for automation and repeatable deployments. AWS CloudFormation or Terraform takes you further — they let you define entire infrastructure in code.