11-tooling-cloud-ai-awareness

Cloud Basics for Backend Engineers: EC2, S3, RDS, IAM, CloudWatch

Enough AWS to be dangerous: EC2 instance types, S3 storage, RDS databases, IAM roles, and CloudWatch observability.

August 14, 2026
backend-engineerawsec2s3rdsiam

Cloud Basics

You don't need an AWS certification to be effective as a backend engineer, but you do need enough cloud fluency to reason about where your service runs, where its data lives, who's allowed to touch what, and how you'd know if something broke. This guide covers the five AWS services that show up in almost every backend job — EC2, S3, RDS, IAM, and CloudWatch — at the depth a backend engineer actually uses them, not the depth a cloud architect needs.


1. Why This Matters Even If "DevOps Owns Infra"

Even on teams with a dedicated platform/DevOps function, backend engineers routinely need to:

  • Debug why a service can't reach a database (security group / VPC issue)
  • Understand why an S3 upload is failing (IAM permissions, not application bugs)
  • Read CloudWatch metrics to diagnose a memory leak or throttling
  • Estimate the cost impact of a design choice (an unbounded S3 ListObjects loop, an oversized RDS instance)
  • Reason about instance sizing when proposing a new service
💡

The mental model that transfers everywhere: cloud "primitives" map to things you already understand — EC2 is a server, S3 is a filesystem/blob store accessed over HTTP, RDS is a managed database, IAM is an authorization system, and CloudWatch is logging + metrics + alerting. The complexity is in the knobs, not the concepts.


2. EC2: Elastic Compute Cloud

EC2 gives you a virtual machine — a raw server you control at the OS level. It's the foundation everything else (including container platforms like ECS/EKS) ultimately runs on top of.

Instance families

FamilyOptimized forBackend use case
T-series (t3, t4g)Burstable, low baseline costDev/staging, low-traffic services
M-series (m6i, m7g)Balanced CPU:memoryGeneral-purpose API services (most common default)
C-series (c6i, c7g)Compute-optimized (high CPU:memory ratio)CPU-bound workloads — encoding, heavy computation
R-series (r6i, r7g)Memory-optimizedIn-memory caches, large JVM heaps, data processing
I-series (i4i)High local NVMe I/OSelf-managed databases, high-throughput storage

The g suffix (e.g., m7g, t4g) denotes Graviton — AWS's ARM-based processors. They're typically 20-40% cheaper for the same performance on workloads that don't depend on x86-specific native libraries. For a standard Spring Boot service on a JVM, Graviton is usually a safe, meaningful cost win — verify your base Docker image has ARM64 support first.

Purchasing options

OptionDiscount vs on-demandCommitmentBest for
On-DemandNone (baseline)NoneUnpredictable or short-lived workloads
Reserved Instances~40-60%1-3 year termSteady-state production baseline capacity
Savings Plans~40-65%1-3 year $/hr commitmentFlexible across instance families
Spot InstancesUp to 90%None, but can be reclaimed with ~2 min noticeStateless, interruption-tolerant batch/worker jobs
⚠️

Never run your primary stateful database or a service that can't tolerate sudden termination on Spot Instances. Spot is excellent for stateless horizontally-scaled workers (batch jobs, async queue consumers) that can be safely retried elsewhere.

Sizing in practice

bash
# From an EC2 instance, check what you're actually using before resizing
top                     # CPU/memory snapshot
vmstat 1 5              # memory, swap, CPU over 5 seconds
free -h                 # memory headroom
 
# Right-sizing rule of thumb: if steady-state CPU is consistently
# under 30-40%, you're likely over-provisioned. If it's pinned near
# 100% under normal load with no headroom for spikes, scale up or out.

3. S3: Simple Storage Service

S3 is object storage — think of it as a massively durable, HTTP-accessible key-value store for files, not a filesystem you mount and randomly seek within.

Storage classes

ClassRetrievalCostUse case
S3 StandardMillisecondsHighestFrequently accessed files (user uploads, active assets)
S3 Intelligent-TieringMillisecondsAuto-optimizedUnknown/changing access patterns
S3 Standard-IA (Infrequent Access)MillisecondsLower storage, retrieval feeBackups accessed occasionally
S3 Glacier Instant RetrievalMillisecondsVery lowCompliance archives needing occasional fast access
S3 Glacier Flexible RetrievalMinutes to hoursLowestLong-term archives, rarely accessed

A backend engineer's actual S3 usage

java
// Generating a presigned URL — lets a client upload/download directly to S3
// without your service proxying the bytes through its own compute
S3Presigner presigner = S3Presigner.create();
 
PutObjectRequest putRequest = PutObjectRequest.builder()
    .bucket("acme-invoices")
    .key("invoices/2026/08/inv-" + invoiceId + ".pdf")
    .contentType("application/pdf")
    .build();
 
PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(
    b -> b.signatureDuration(Duration.ofMinutes(10)).putObjectRequest(putRequest)
);
 
String uploadUrl = presignedRequest.url().toString();
// Return uploadUrl to the client; it PUTs the file directly to S3

Presigned URLs are the standard pattern for file uploads/downloads in a backend service. Proxying large file bytes through your application server wastes compute, memory, and bandwidth on work that's purely I/O. Generate a short-lived presigned URL and let the client talk to S3 directly.

Key S3 concepts for backend work

  • Buckets are globally named, regionally located — bucket names are unique across all of AWS, but the data lives in one region.
  • Keys are strings, not pathsinvoices/2026/08/inv-123.pdf looks like a directory structure but S3 is a flat key-value namespace; the "folders" in the console are a UI convenience.
  • Versioning protects against accidental overwrite/delete — enable it on buckets holding anything irreplaceable.
  • Lifecycle rules automatically transition or expire objects (e.g., move to Glacier after 90 days, delete after 7 years) — set these instead of writing cleanup cron jobs.
  • Bucket policies vs IAM policies: a bucket policy is attached to the bucket (resource-based); an IAM policy is attached to a user/role (identity-based). Both are evaluated, and either can grant or deny.

4. RDS: Relational Database Service

RDS is a managed relational database — AWS handles patching, backups, failover, and storage scaling, while you keep full SQL access to the engine of your choice (PostgreSQL, MySQL, etc.).

FeatureWhat it doesWhy it matters
Multi-AZ deploymentSynchronous standby replica in a different Availability ZoneAutomatic failover (~1-2 min) on primary failure, no manual intervention
Read replicasAsynchronous copies, can serve read trafficOffload reporting/analytics queries from the primary; replicas can lag
Automated backupsDaily snapshot + transaction logsPoint-in-time restore to any second within the retention window
Storage autoscalingGrows storage automatically as data growsAvoids manual intervention for growing tables
Parameter groupsEngine-level config (max connections, buffer sizes)Tune the database engine without SSH access to the underlying host
⚠️

Read replicas are eventually consistent, not synchronous. A common bug: writing data then immediately reading it back from a replica for the same request — the write may not have propagated yet, and the read returns stale or missing data. Route read-after-write logic to the primary, and use replicas only for queries that can tolerate lag (reporting, dashboards, search indexing).

bash
# Connecting from an app — the connection string is the entire "cloud"
# abstraction most backend code actually needs to know about
jdbc:postgresql://order-db.abc123xyz.us-east-1.rds.amazonaws.com:5432/orders
💡

Multi-AZ is for availability, not read scaling. The standby in a Multi-AZ pair is not queryable — it exists purely as a failover target. If you need to scale read throughput, add read replicas separately; Multi-AZ and read replicas solve different problems and are often used together.


5. IAM: Identity and Access Management

IAM controls who (identity) can do what (action) to which resource (scope), and is the single most important AWS service to understand correctly — misconfigured IAM is the root cause of most cloud security incidents.

Core concepts

ConceptWhat it is
UserA long-lived identity for a person (or, historically, an application — now discouraged)
RoleA temporary identity assumed by a service, application, or federated user — no long-lived credentials
PolicyA JSON document defining allowed/denied actions on resources
GroupA collection of users sharing the same policies
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowInvoiceBucketReadWrite",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::acme-invoices/invoices/*"
    },
    {
      "Sid": "AllowListBucketOnly",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::acme-invoices",
      "Condition": {
        "StringLike": { "s3:prefix": "invoices/*" }
      }
    }
  ]
}
🚨

The single most important IAM habit: least privilege, scoped resources, never "Action": "*" on "Resource": "*". A policy that grants an EC2 instance role full S3 access "to make development easier" turns a minor application bug into an incident where every bucket in the account is readable/writable from a compromised service.

Roles for EC2/ECS — never hardcode credentials

Never put AWS access keys in application config, environment variables in source control, or .env files committed to Git. Attach an IAM role to the EC2 instance, ECS task, or Lambda function instead — the AWS SDK automatically discovers and rotates temporary credentials via the instance/task metadata service. This eliminates an entire category of leaked-credential incidents.

Policy evaluation logic

  1. By default, everything is implicitly denied.
  2. An explicit Allow in any applicable policy grants the permission.
  3. An explicit Deny anywhere always wins, overriding any Allow.

6. CloudWatch: Logs, Metrics, and Alarms

CloudWatch is where you go to answer "is it broken, and why" without SSH-ing into anything.

CapabilityWhat it doesExample use
LogsCentralized, searchable log aggregationApplication logs shipped from EC2/ECS via the CloudWatch agent
MetricsTime-series numeric data (CPU, memory, request count, custom app metrics)CPUUtilization, DatabaseConnections, a custom orders.created counter
AlarmsThreshold-based triggers on a metricPage on-call if p99 latency > 2s for 5 consecutive minutes
DashboardsVisual composition of metrics/logsAn "Order Service Health" dashboard for on-call
Logs InsightsQuery language over log data`fields @timestamp, @message
bash
# CloudWatch Logs Insights query — find the top error types in the last hour
fields @timestamp, @message
| filter @message like /ERROR/
| stats count(*) as errorCount by bin(5m)
| sort errorCount desc

A realistic alarm

yaml
# CloudFormation-style alarm definition
Type: AWS::CloudWatch::Alarm
Properties:
  AlarmName: order-service-high-p99-latency
  MetricName: TargetResponseTime
  Namespace: AWS/ApplicationELB
  ExtendedStatistic: p99
  Period: 60
  EvaluationPeriods: 5
  Threshold: 2.0
  ComparisonOperator: GreaterThanThreshold
  AlarmActions:
    - arn:aws:sns:us-east-1:123456789012:pagerduty-critical
💡

Custom application metrics matter as much as infrastructure metrics. CPU and memory tell you the box is healthy; they don't tell you that checkout is failing. Emit business-relevant metrics from your service (orders.created, payment.failed, queue.depth) alongside the infrastructure defaults — that's usually what actually pages you before customers notice.


7. Cost Awareness

Cost is a design constraint, not just a finance concern. A few habits that consistently matter:

  • Right-size before you scale out — an oversized m6i.2xlarge running at 15% CPU is a bigger, cheaper-to-fix problem than most people assume.
  • S3 lifecycle rules over manual cleanup — transitioning to Glacier or expiring old objects is nearly free to set up and directly reduces storage cost every month.
  • Watch data transfer, not just compute — cross-AZ and cross-region traffic is billed and frequently the surprise line item on a bill.
  • Reserved Instances / Savings Plans for steady-state baseline — Spot/On-Demand for elastic peaks on top of that baseline.
  • CloudWatch alarms on cost anomalies, not just performance — AWS Budgets/Cost Anomaly Detection catches a runaway PutMetricData loop or a forgotten unused RDS instance before it becomes a five-figure surprise.

Key takeaways

  • Cloud services map to concepts you already know — EC2 is a VM, S3 is object storage over HTTP, RDS is a managed database, IAM is authZ, CloudWatch is logs/metrics/alarms. Complexity is in configuration, not concepts.
  • Use Graviton (ARM, g-suffix) instance types by default for standard JVM workloads — meaningful cost savings with no code change, provided your images support ARM64.
  • Presigned S3 URLs let clients upload/download directly, keeping large file bytes off your application servers entirely.
  • Read replicas are asynchronous and can lag — never rely on immediate read-after-write consistency against a replica.
  • Multi-AZ RDS is for failover/availability; it is not a mechanism for scaling read throughput — use read replicas for that.
  • IAM roles attached to EC2/ECS/Lambda eliminate the need for hardcoded credentials — the SDK fetches and rotates temporary credentials automatically.
  • An explicit Deny in any IAM policy always wins over any Allow, and everything is implicitly denied unless explicitly allowed.
  • Emit custom application metrics (business events, not just infrastructure) to CloudWatch — infra health and business health are different signals.

Interview Questions

  • What's the difference between EC2, ECS, and Lambda, and when would you choose each?
  • Why might you choose a Graviton (ARM) instance over an equivalent x86 instance?
  • What's the difference between On-Demand, Reserved, Savings Plans, and Spot pricing? What workloads suit Spot?
  • What is a presigned URL in S3, and why is it preferable to proxying file uploads through your application server?
  • Explain S3 storage classes and when you'd use Glacier vs Standard-IA vs Standard.
  • What's the difference between RDS Multi-AZ and RDS read replicas? What problem does each solve?
  • Why can reading from a read replica immediately after a write return stale data? How would you work around it?
  • What is the difference between an IAM user, an IAM role, and an IAM policy?
  • Why is attaching an IAM role to an EC2 instance preferred over storing AWS access keys in application configuration?
  • How does IAM policy evaluation work when there's both an Allow and a Deny that apply to the same request?
  • What's the difference between a CloudWatch metric and a CloudWatch log, and when do you reach for each while debugging?
  • How would you set up an alarm to page on-call when p99 latency exceeds a threshold?
  • What's the practical difference between a bucket policy and an IAM policy for controlling S3 access?
  • Describe how you'd right-size an EC2 instance that appears over-provisioned.