EC2 Security Groups — SSH 0.0.0.0/0 to Miner in 24h
t3.
- EC2 = virtual server rental. Pay per second. Stop = compute stops billing, EBS continues. Terminate = delete instance and root volume.
- Instance families: t (burstable credits), c (compute), r (RAM), i (storage), g (GPU). Never use t3.micro for production sustained load.
- Security groups = stateful firewall. 0.0.0.0/0 on SSH = crypto mining within 24 hours. Always restrict to your IP.
- EBS: gp3 is cheaper than gp2 and decouples IOPS from size. Default gp2 is a trap for new accounts.
- Pricing: On-Demand (no commitment), Savings Plans (flexible, 72% off), Reserved Instances (inflexible, locks instance type), Spot (90% off, can be interrupted).
- Production killer: setting ClockSkew = 0 in JWT validation — server drift by 30 seconds locks out all users.
Imagine you need a powerful gaming PC to run a tournament, but you only need it for one weekend. Instead of buying one, you rent it from a warehouse that has thousands of PCs in every size. AWS EC2 is that warehouse — except instead of gaming PCs, it's servers. You rent exactly the computing power you need, for exactly as long as you need it, and when you're done, you hand it back and stop paying. That's it.
Every app you've ever built eventually hits the same wall: where does it actually run? Your laptop can't serve production traffic, a shared hosting plan falls over under load, and buying physical servers means you're locked into hardware that's obsolete in three years. The cloud exists to solve this, and AWS EC2 is where most teams start — and for good reason. It's the backbone of thousands of production systems running right now, from early-stage startups to Fortune 500 backends.
EC2 (Elastic Compute Cloud) solves the problem of unpredictable infrastructure needs. 'Elastic' is the key word — you can spin up 50 servers at 9am for a product launch and terminate 48 of them by noon when the traffic spike passes. You're billed by the second. No contracts, no idle hardware, no datacenter lease. The underlying model shifts infrastructure from a capital expense (buy servers) to an operational one (rent compute), which changes how engineering teams think about scaling entirely.
By the end of this article you'll understand what an EC2 instance actually is under the hood, how to choose the right instance type for your workload, how to launch and connect to a real server using the AWS CLI, and how to lock it down with security groups. You'll also see the exact mistakes that burn people — including accidental bills from instances left running and SSH connections that silently refuse to work.
EC2 Instance Types and Pricing — Stop Paying for What You Don't Need
AWS divides instance types into families based on the ratio of CPU, memory, storage, and network. Pick wrong and you overpay or underperform.
General purpose (t3, m6i) — balanced CPU/memory. Good for web servers, dev/test environments. The t3 family includes burstable credits: you earn credits when idle and burn them under load. Exhaust them and the instance throttles.
Compute optimized (c6i, c7g) — higher CPU-to-memory ratio. For batch processing, video encoding, high-performance web servers. c6i is Intel, c7g is Graviton (ARM) — ~20% better price/performance.
Memory optimized (r6i, x2iedn) — massive RAM per vCPU. For in-memory databases (Redis, SAP HANA), large caches. The x2iedn gives up to 4 TB RAM.
Storage optimized (i3, d2) — high local NVMe SSD. For data warehouses, log processing. d2 has spinning disks for cold storage.
GPU instances (p4, g5) — for machine learning, graphic rendering. p4 uses A100 GPUs; g5 uses NVIDIA A10G.
In production, you usually start with a small general-purpose for your app, then use CloudWatch to profile actual resource usage and right-size after a week. Most teams over-provision by 2–3x initially.
Pricing models: - On-Demand: Pay per second, no commitment. Highest per-hour cost. Best for short-lived workloads. - Savings Plans: Commit to $/hour spend for 1-3 years (up to 72% off). Flexible across instance families and regions. - Reserved Instances: Commit to specific instance family in specific AZ for 1-3 years. Inflexible, but up to 75% off. Lock-in risk. - Spot Instances: Spare capacity, up to 90% off, but can be terminated with 2-min warning. Use for batch, CI/CD, stateless workloads.
Cost optimisation trap: buying a 3-year RI for a project that gets cancelled after 6 months. You're stuck paying for the entire term. Start with Savings Plans — they're flexible.
One nuance: the Graviton-based types (c7g, m7g, r7g) offer better price-performance for most workloads, but you'll need ARM-compatible software. Most container images and modern language runtimes work fine, but legacy binaries might not. Test before you commit.
- t3.micro baseline: 10-20% of a full vCPU. Burst to 100% for short periods.
- CPUCreditBalance = 0 → instance is throttled. Your app slows down.
- For sustained >20% CPU for more than a few hours, switch to m6i.large.
- Enable 'unlimited' mode for t3 — costs extra when credits negative. Use only for unexpected spikes.
- Production databases on t3.micro = slow queries + unhappy customers.
Instance Family Comparison Table — C, M, R, T, I, G Series at a Glance
When selecting an instance, start with the family. Each family optimises a different resource ratio. The table below shows the common families, representative types, the vCPU-to-memory ratio, typical use cases, and approximate on-demand hourly pricing (us-east-1, as of May 2026). Prices are for the smallest size in each family and increase with size.
| Family | Example Types | vCPU:RAM Ratio | Common Use Cases | ~Min Hourly Price (On-Demand) |
|---|---|---|---|---|
| T (Burstable) | t3.nano - t3.2xlarge | 1:2 (t3.micro) | Dev/test, low-traffic web servers, microservices with sporadic load | $0.0104 (t3.nano) |
| M (General) | m6i.large - m6i.32xlarge | 1:4 | Web servers, application servers, small databases | $0.096 (m6i.large) |
| C (Compute) | c6i.large - c6i.32xlarge | 1:2 | Batch processing, video encoding, high-performance web servers | $0.085 (c6i.large) |
| R (Memory) | r6i.large - r6i.32xlarge | 1:8 | In-memory databases (Redis, Memcached), real-time analytics | $0.126 (r6i.large) |
| I (Storage) | i3.large - i3.16xlarge | 1:4 + NVMe | Data warehouses, log processing, NoSQL databases | $0.156 (i3.large) |
| G (GPU) | g5.xlarge - g5.48xlarge | 1:4 + GPU | Machine learning training/inference, graphics rendering | $1.006 (g5.xlarge) |
| X (Memory-optimised) | x2iedn.xlarge - x2iedn.32xlarge | 1:16 | SAP HANA, large in-memory databases | $0.557 (x2iedn.xlarge) |
Graviton (ARM) variants (c7g, m7g, r7g) offer 20% better price/performance than equivalent Intel/AMD types for most workloads. For example, c7g.large costs ~$0.068/hr vs c6i.large at $0.085/hr. Check software compatibility before migrating.
How to choose: - If your CPU is pegged at 100% but memory is under 50%, you need a compute-optimised type (C or better). - If memory is near capacity but CPU is idle, move up to R series. - If you need high local I/O (e.g., for temporary data processing), pick I series with instance store. - For GPU-accelerated workloads, G or P series. P (p4, p5) are even more powerful but more expensive.
Use the AWS CLI to list available instance types in your region: aws ec2 describe-instance-types --filters Name=instance-type,Values=t3. --query 'InstanceTypes[].[InstanceType,VCpuInfo.DefaultVCpus,MemoryInfo.SizeInMiB]' --output table
Pricing Model Decision Matrix — Choose Between On-Demand, Reserved, Spot, and Savings Plans
EC2 offers multiple pricing models, and choosing the wrong one can double your costs or leave you locked into a commitment you can't change. This decision matrix maps each model's commitment level, discount depth, interruptibility, and ideal use case.
| Pricing Model | Commitment Required | Max Discount | Interruptible? | Best For |
|---|---|---|---|---|
| On-Demand | None | 0% | No | Short-lived workloads, spiky traffic, development, workloads with unpredictable duration |
| Reserved Instance (Standard) | 1 or 3 years, specific instance family + region | Up to 75% | No | Steady-state production workloads where instance type and region are certain for 1-3 years |
| Reserved Instance (Convertible) | 1 or 3 years, but can change family/region (within same OS) | Up to 60% | No | Workloads that are steady but may need to migrate instance family (e.g., upgrade from M to R) |
| Compute Savings Plans | 1 or 3 years, $/hour commitment across any EC2 instance family and region | Up to 66-72% | No | Most flexible commitment; best for diversified workloads where instance types vary |
| Spot Instances | None (but may be interrupted) | Up to 90% | Yes (2-min warning) | Stateless, fault-tolerant tasks: batch processing, CI/CD, big data, image processing, microservices with graceful shutdown |
Decision flow: 1. Will the workload run continuously for 1-3 years? -> Yes -> Consider Savings Plans or RIs. Start with Compute Savings Plans for flexibility. 2. Can the workload tolerate interruption? -> Yes -> Use Spot Instances for maximum savings. If no, use On-Demand or Savings Plans. 3. Is the instance type and region known to be fixed? -> Yes -> Standard RI gives highest discount (up to 75%) but locks you in. For most teams, Savings Plans are safer. 4. Is the workload short or unpredictable? -> On-Demand is the simplest. Never commit to RI/Savings Plans for short projects.
Common pitfall: A developer committed to a 3-year Standard RI for an application that migrated to containers 6 months later. The RI was tied to a specific instance type and region, so it became useless. The cost: $50,000 paid for compute they never used.
Best practice: Use a mix: On-Demand for baseline flexibility, Savings Plans for steady-state capacity (covering about 60-80% of your expected usage), and Spot for elastic workloads that can be restarted. This blend gives you cost efficiency without lock-in risk.
Security Groups — The Firewall That Saves You from Crypto Miners
Security groups (SGs) are stateful virtual firewalls attached to EC2 (and other AWS resources). They control inbound and outbound traffic based on rules you define.
Key properties: - Stateful: if you allow inbound on port 80, response traffic is automatically allowed outbound regardless of outbound rules. - Explicit allow: no deny rules — only allow. Traffic that isn't allowed is implicitly denied. - Reference other security groups: you can allow inbound from another SG (e.g., allow HTTP from ALB SG), which is more secure than IP ranges. - You can attach up to 5 SGs per instance.
Common patterns: - Web tier: allow HTTP (80) and HTTPS (443) from 0.0.0.0/0; allow SSH from your office IP only. - App tier: allow traffic only from the web tier SG on application port. - Database tier: allow traffic only from app tier SG on DB port (e.g., 3306 for MySQL). Never allow DB ports from 0.0.0.0/0.
Mistake to avoid: Opening all ports to 0.0.0.0/0 for 'convenience'. That's how your instance becomes a crypto mining node overnight.
SSH-specific best practices: - Never open 0.0.0.0/0 on port 22. Ever. Bots scan every IP every 15 minutes. - Use AWS Systems Manager Session Manager instead of SSH — no public IP needed, no SSH keys, audit logs built-in. - If you must use SSH, restrict to your office IP using --cidr $(curl -s http://checkip.amazonaws.com)/32. - Use EC2 Instance Connect (temporary SSH key pushed via IAM).
Worst-case scenario: A client opened port 3306 (MySQL) to 0.0.0.0/0 for 'easy testing' and forgot to revert. Within 3 hours, their database was publicly accessible and a script dumped all tables. The data breach cost $500k in fines.
EBS Volumes — gp3 vs gp2 and the Burst Credit Trap
Amazon Elastic Block Store (EBS) provides block-level storage volumes that persist independently from your EC2 instance. Think of it as an external hard drive you can attach/detach at will.
Volume types: - gp3 (General Purpose SSD): baseline 3000 IOPS, burst to 16000. Good for most workloads. Cost-optimised. Recommended for new deployments. - gp2 (older): IOPS tied to volume size (3 IOPS per GB). Baseline 3 IOPS/GB with burst credits (up to 3000 IOPS). Avoid for new deployments unless you need compatibility. - io1/io2 (Provisioned IOPS): guaranteed IOPS, expensive. For databases requiring consistent, high IOPS. - st1 (Throughput Optimized HDD): cheap, high throughput. For log processing, big data. - sc1 (Cold HDD): lowest cost, infrequent access.
The gp2 burst trap: gp2 earns I/O credits when idle (like CPU credits). Under sustained high I/O, credits exhaust, and performance drops from 3000 IOPS to baseline (3 IOPS per GB). A 100GB gp2 volume would drop to 300 IOPS.
gp3 eliminates burst credits: baseline 3000 IOPS regardless of size, and it's often cheaper than gp2. Migrate any gp2 volumes to gp3 for consistent performance and lower cost.
Performance tip: gp3 decouples IOPS from size and is cheaper than gp2. For high-performance databases, use io2 Block Express (up to 256,000 IOPS).
Encryption warning: By default, EBS encryption is not enabled in a new account. Enable it at the account level via the EC2 console settings. Otherwise, any snapshot you share accidentally could leak data.
Storage Comparison — EBS vs Instance Store
EC2 instances have two storage options: Elastic Block Store (EBS) volumes and Instance Store volumes (ephemeral). They differ fundamentally in persistence, performance, and pricing. Choosing incorrectly can lead to data loss or unexpected costs.
EBS (Elastic Block Store): - Network-attached block storage that persists independently of the instance. - Can be detached and reattached to another instance. - Data survives instance stop, start, and terminate (unless you choose 'delete on termination' for the root volume). - Multiple volume types (gp3, io2, st1, sc1) with different performance/cost profiles. - Billed per GB-month plus IOPS/throughput provisions. - Typical latency: 1-5 ms.
Instance Store (Ephemeral Storage): - Physically attached to the host server that runs the instance. - Data is lost when the instance is stopped, terminated, or the underlying host fails. - Included in the instance price — no separate billing. - Extremely low latency (sub-millisecond) and very high IOPS (millions on NVMe). - Only available on certain instance types (i3, i4i, m5d, c5d, r5d, etc. — look for 'd' suffix for local NVMe). - Cannot be detached or moved to another instance.
| Feature | EBS | Instance Store |
|---|---|---|
| Persistence | Survives stop/terminate | Lost on stop/terminate/host failure |
| Performance | Network-attached, 1-5ms latency | Direct-attached, sub-ms latency, millions IOPS |
| Cost | Pay per GB-month + IOPS | Included in instance price (no extra) |
| Size limit | Up to 64 TB per volume (by request) | Up to ~60 TB per instance (multiple NVMe) |
| Snapshot support | Yes (snapshots to S3) | No |
| Encryption | Supports KMS/SSE | Supports instance-level encryption |
| Detach/reattach | Yes | No |
| Use cases | Databases, OS boot volumes, persistent application data | Temporary storage, caches, scratch data, log processing, swap |
Best practices: - Always use EBS for persistent data like databases, application state, and logs you need to keep. - Use Instance Store for temporary data that can be regenerated: build caches, intermediate processing results, swap space, or data replicated from another source. - Many production architectures combine both: boot from EBS (gp3), and mount instance store NVMe for high-performance scratch space (e.g., database temp tables, MapReduce shuffle). - If you use Instance Store for anything important, replicate it across instances or to a shared EBS/EFS/S3 to avoid single-point-of-failure.
Common mistake: A developer used an instance store volume as the primary data store for a stateful application. When the instance was stopped for a security patch, all data was lost. Recovery took days from backups. Always review the 'Delete on termination' flag and instance type storage options before launching.
The t3.micro That Cost $2,300 in One Weekend
- 0.0.0.0/0 on SSH is not 'low risk' — it's a guarantee of compromise within 24-48 hours.
- Every instance needs CloudWatch billing alarm and CPU/disk monitoring.
- t3.micro is fine for testing, but set termination protection and expiration tags.
- Don't attach IAM roles with S3 read access to public-facing instances.
- Use AWS Systems Manager Session Manager instead of SSH for production access.
Key takeaways
Common mistakes to avoid
7 patternsOpening SSH port to 0.0.0.0/0 and using default security groups
--cidr $(curl -s http://checkip.amazonaws.com)/32. Use Systems Manager Session Manager for production access. Create a custom security group with minimal rules.Leaving instances running after testing
expiration-date: 2026-05-01). Set up CloudWatch alarms on billing. Use AWS Instance Scheduler to auto-stop instances outside work hours. Terminate instead of stop when done.Using t2/t3 micro for production services
unlimited mode (costs extra when credits are negative).Storing secrets (API keys, passwords) in user data or AMIs
Not encrypting EBS volumes by default
Not enabling termination protection on production instances
aws ec2 modify-instance-attribute --instance-id <id> --attribute disableApiTermination --value true. Set IAM policies that require MFA to disable termination protection.Using the default VPC without understanding its limits
Interview Questions on This Topic
Explain the different EC2 instance purchase options and when you would use each.
Frequently Asked Questions
That's Cloud. Mark it forged?
11 min read · try the examples if you haven't