From Servers to Cloud: How I Finally Understood the Basics of AWS
AWS Networking for People Who Just Want Things to Work — Subnets, CIDR, Peering, and Why the Default VPC Exists

Before you read this — here's what you should already know
This is Part 2 of the AWS for Absolute Beginners series. If you haven't read Part 1 yet, go read that first. I talk about what a server actually is, why the cloud exists, and why AWS specifically.
Quick pre-requisites before we go further:
You know what a server is (physical or virtual machine that responds to requests)
You've at least seen the AWS console once — EC2, regions, something
You've heard the word "IP address" before, even if you don't fully get it yet
You understand that the internet is how computers talk to each other across the world
That's it. You don't need to be a networking expert. I wasn't one when I started learning this stuff.
Let me tell you what confused me the most when I first opened the AWS console.
There was already a VPC there. I hadn't created anything yet. No EC2 instance, no database, nothing. But a VPC was just... sitting there. Default VPC, us-east-1.
I ignored it for weeks. Then I accidentally deleted it one day while cleaning up resources. And suddenly nothing worked the way it was supposed to.
That's when I actually started paying attention.
Why Does AWS Always Keep a Default VPC?
Here's the short answer: because without a VPC, you literally cannot run anything on AWS.
EC2 instances don't float in some abstract cloud space. They need to live inside a network. That network is the VPC. Every resource you launch — EC2, RDS, Lambda inside a VPC — needs to know what network it belongs to, what IP range it can use, and what it's allowed to talk to.
The default VPC is AWS saying: "We know networking is confusing. Here's one that already works so you can actually get started."
It comes pre-configured with everything you need to just... launch stuff and have it work. Internet access, subnets in every availability zone, a route table, an internet gateway — all of it. Ready to go.
If there was no default VPC, every tutorial, every beginner launching their first EC2 instance would have to understand subnets, CIDRs, route tables, and internet gateways before they could do anything at all. Most people would give up.
The default VPC is a shortcut. A good one.
That said — in production? You don't use the default VPC. You build your own, with the exact subnets, access rules, and routing you actually need. The default VPC is for learning and quick experiments. It's not where your customer data should live.
Regions, Availability Zones, and Edge Locations
These three things get lumped together a lot. They're not the same thing at all.
Regions are physical locations in the world where AWS has data centers. us-east-1 is Northern Virginia. ap-south-1 is Mumbai. eu-west-1 is Ireland. When you launch an EC2 instance in ap-south-1, it physically runs on servers in Mumbai. The resources stay there unless you explicitly move them.
Why does this matter? Latency. If your users are in India and your server is in Virginia, every request travels halfway around the world. That's slow. Also, some data has legal requirements about where it can be stored — Indian financial data staying in India, GDPR data staying in Europe. Regions handle that.
Availability Zones (AZs) are what live inside each region. Each AZ is a separate physical data center — separate power, separate cooling, separate network. ap-south-1 has ap-south-1a, ap-south-1b, and ap-south-1c.
The whole point is isolation. If ap-south-1a goes down (fire, flood, power failure), ap-south-1b and ap-south-1c are unaffected. So when you run production workloads, you spread them across multiple AZs. Your app keeps running even if one data center has a problem.
Single-AZ deployments are cheaper. Multi-AZ deployments are resilient. Pick based on what your app actually needs.
Edge Locations are different. These aren't where you run servers. These are where AWS caches content close to users.
CloudFront is the main service here. Say your app is in Mumbai but someone in Chennai requests a video. Instead of hitting Mumbai every time, CloudFront caches that video at an edge location in Chennai. The user gets it fast. Your origin server doesn't get hammered.
There are 400+ edge locations globally. Many more than there are regions. They exist purely to make delivery faster for end users.
One thing worth knowing: AWS Local Zones and Wavelength Zones are variations of this concept — they bring compute even closer to specific cities or 5G networks. You probably won't use these early on, but they exist under the same umbrella idea.
The Internet vs a VPC
This comparison is actually the most useful mental model for understanding what VPCs do.
The internet is a global public network. Any device on it can try to reach any other device. Your laptop, a server in Japan, a phone in Brazil — all reachable from each other (firewall rules aside). Nobody owns the internet. It's open by default.
A VPC is a private network that you own and control inside AWS. You define the IP range. You decide which subnets exist. You decide what can talk to what, and what can reach the internet and what can't.
Nothing gets in or out of your VPC unless you explicitly allow it. That's the whole point.
Think of it like this: the internet is a public road system. Anyone can drive on it. A VPC is a gated community with its own private roads. You decide who gets a key card, which roads connect to the public highway, and which buildings are accessible from outside at all.
Your database shouldn't be on the public internet. Put it in a private subnet inside your VPC. Only your application servers (which you can selectively expose) talk to it. The database is invisible to the outside world.
That's not a configuration trick. That's just how VPCs work.
Public Cloud vs Private Cloud vs Hybrid Cloud
I got asked this in an interview once. I over-explained it. Here's the version I wish I'd given.
Public Cloud is what AWS, Azure, and GCP are. The infrastructure is owned and maintained by the provider. You rent it. You share physical hardware with other customers (though your data is isolated). You pay for what you use. You don't manage any servers.
This is what most startups and modern companies use. Low upfront cost, scales instantly, someone else handles the hardware.
Private Cloud is infrastructure that you own and operate yourself, but run with cloud-like management tools. A company buys servers, puts them in their own data center, and runs software like VMware or OpenStack on top to get elastic provisioning, self-service, etc. It looks and feels like a cloud — but it's entirely yours.
Banks, government agencies, defense companies go this route. Full control, no data leaving your premises. But expensive to build and maintain.
Hybrid Cloud is both, connected together. Some workloads run on public cloud (AWS), others stay on-prem in private infrastructure, and they talk to each other over a secure connection (AWS Direct Connect or VPN).
A bank might run customer-facing APIs on AWS for the scalability, but keep core transaction processing on-prem because regulations require it. That's hybrid.
AWS Outposts is worth knowing here — it's AWS hardware that you install in your own data center. You get the AWS APIs and services, but the compute runs physically on your site. Classic hybrid setup.
The choice isn't about which is "better." It's about regulatory requirements, cost tolerance, control needs, and existing infrastructure.
IP Addresses and CIDR — Actually Simple
An IP address is just a unique identifier for a device on a network. Like a house address. 192.168.1.5 means "this specific machine, on this specific network."
IPv4 addresses look like four numbers separated by dots: 192.168.1.5. Each number is between 0 and 255. There are about 4.3 billion possible IPv4 addresses — which sounds like a lot until you realize there are 8 billion people and way more devices than that.
So now we have CIDR. It stands for Classless Inter-Domain Routing. Ignore the name.
CIDR is just a way to describe a range of IP addresses in shorthand.
10.0.0.0/16 — what does this mean?
The number after the slash (/16) tells you how many bits are fixed. IPv4 addresses are 32 bits total. So /16 means the first 16 bits are fixed, and the remaining 16 bits are yours to use.
10.0.0.0/16 = all addresses from 10.0.0.0 to 10.0.255.255
That's 65,536 addresses. (2 to the power of 16 = 65,536)
10.0.1.0/24 = first 24 bits fixed, 8 bits available = 256 addresses (10.0.1.0 to 10.0.1.255)
10.0.1.0/28 = first 28 bits fixed, 4 bits available = 16 addresses
The higher the number after the slash, the smaller the range.
When you're building a VPC, you pick a CIDR block for the whole VPC — say 10.0.0.0/16. That gives you 65,536 IPs to work with. Then you carve it into subnets: maybe 10.0.1.0/24 for your public subnet, 10.0.2.0/24 for your private subnet, etc.
AWS actually reserves 5 IPs from every subnet for its own use (network address, router, DNS, future use, broadcast). So a /24 subnet gives you 251 usable IPs, not 256. Worth knowing when you're planning.
VPC Resources — What They Are and What They Actually Do
When you build a VPC from scratch, AWS gives you a blank canvas. No internet access, no routing, no nothing. You have to wire everything yourself. Here's every piece you need and what it actually does.
Subnets
Subnets divide your VPC's IP range into smaller chunks. If your VPC is 10.0.0.0/16, you might create:
10.0.1.0/24as a public subnet (for EC2 instances that need to be reachable from the internet)10.0.2.0/24as a private subnet (for databases, internal services that should never be directly exposed)
The "public/private" label isn't a built-in AWS toggle. It comes entirely from routing. A subnet becomes "public" when its route table has a route to an internet gateway. That's it. No route to IGW = private, no matter what you name it.
One more thing: subnets live inside a single AZ. If you want resources in multiple AZs (which you should, for production), you create subnets in each AZ. A common pattern is two public subnets (one per AZ) and two private subnets (one per AZ). Four subnets total for a basic highly-available setup.
Internet Gateway (IGW)
The IGW is the single door between your entire VPC and the public internet. One per VPC — you can't have two. Without it, your VPC is completely air-gapped from the outside world.
Two steps to make it work:
Create the IGW and attach it to your VPC
Add a route in your public subnet's route table pointing
0.0.0.0/0to the IGW
A lot of people do step 1 and forget step 2. Then they wonder why their EC2 instance has a public IP but can't be reached. The IGW exists but there's no route telling traffic to use it.
Route Tables
Route tables are the GPS of your VPC. Every packet going somewhere checks the route table first: "where should I go?"
Every VPC gets a main route table by default. Every subnet that doesn't have an explicit route table associated uses the main one. That default table only has one rule: route traffic within the VPC (10.0.0.0/16 → local). Local traffic stays local.
For a public subnet, you add: 0.0.0.0/0 → igw-xxxxxxxx
This means: any traffic headed outside the VPC's IP range, send it to the internet gateway.
For a private subnet, you don't add that rule. But if your private instances need outbound internet access (to download packages, hit an API), you add: 0.0.0.0/0 → nat-xxxxxxxx — pointing to a NAT Gateway instead.
One subnet = one route table association at a time. But multiple subnets can share the same route table.
NAT Gateway
This one solves a very specific problem. Your private subnet has a database or an app server. It needs to pull security updates from the internet, or call an external API. But you absolutely don't want anyone from the internet to be able to initiate a connection to it.
NAT Gateway sits in a public subnet (this matters — it needs internet access itself). Your private instances route outbound traffic through it. The NAT makes the outbound request, gets the response, passes it back. From the outside, the traffic looks like it came from the NAT's IP. Your private instance's IP is never exposed.
The key insight: NAT is one-directional. Outbound only. The internet can't reach your private instances through it — NAT doesn't accept inbound connections.
A few things to know:
NAT Gateway needs an Elastic IP attached to it
It lives in one AZ — for HA, create one NAT Gateway per AZ (one in each public subnet) and update each private subnet's route table to use its AZ's NAT
It costs money per hour plus per GB of data processed. Don't leave it running unnecessarily in a learning environment
Elastic IPs
Every time you stop and start an EC2 instance, its public IP changes. That's fine for testing. Not fine for anything real.
Elastic IP is a static public IP address that you allocate to your AWS account. You associate it with an instance (or a NAT Gateway). It stays the same until you explicitly release it.
Common uses: pointing a DNS record at a fixed IP, whitelisting your server's IP with a third-party API, giving your NAT Gateway a stable outbound IP that external services can whitelist.
One catch: AWS charges you for Elastic IPs that are allocated but NOT associated with a running instance. If you allocate one and forget it, you get billed. Release unused EIPs.
The Three CIDRs That Come Up Constantly
When you're setting up security groups and route table rules, you'll keep seeing three values. Here's exactly when to use each:
My IP — your current machine's public IP (e.g., 49.207.x.x/32). The /32 means exactly one IP — yours. Use this for SSH access rules in security groups. It means only you, from your current network, can SSH into the instance. Nobody else, even if they know the password.
The downside: if your ISP gives you a dynamic IP (which most residential ISPs do), this changes. You'll lock yourself out. Update the security group rule when that happens.
VPC CIDR (10.0.0.0/16) — the full IP range of your VPC. Use this when you want any resource inside your VPC to be allowed to talk to another resource. For example: allow your app server's security group to accept traffic from any IP in the VPC range. This means your database in the private subnet can be reached by your EC2 in the public subnet, but nothing from outside the VPC can get in through that rule.
0.0.0.0/0 — everything. The whole internet. Every IP that exists.
In route tables: 0.0.0.0/0 → igw means "send all external traffic to the internet gateway." This is what makes a subnet public.
In security groups: 0.0.0.0/0 on an inbound rule means anyone can reach this port. Port 80 and 443 open to 0.0.0.0/0 is normal for a web server. Port 22 (SSH) open to 0.0.0.0/0 is a security risk — use My IP instead.
The pattern for a secure, functional VPC setup:
SSH on port 22: allow
My IPonlyHTTP/HTTPS (80/443): allow
0.0.0.0/0Database port (3306 for MySQL, 5432 for Postgres): allow your VPC CIDR or the specific security group of your app servers only — never
0.0.0.0/0
VPC Peering — When Two VPCs Need to Talk
By default, VPCs are completely isolated. Two VPCs in the same account, same region — can't talk to each other. Isolation is the whole point of a VPC.
But real architectures need VPCs to communicate. That's what peering is for.
/What Peering Actually Is
A VPC peering connection is a private, direct network link between two VPCs. Traffic travels over AWS's internal backbone — not the public internet, not a VPN, not an IGW. It's low latency, no bandwidth bottleneck, and no extra cost per connection (you pay for data transfer, not the peering connection itself).
Peering works across:
Two VPCs in the same account, same region
Two VPCs in the same account, different regions (inter-region peering)
Two VPCs in different AWS accounts (cross-account peering)
Cross-account is actually common in large companies — different teams or business units have separate AWS accounts for billing and isolation, but their services still need to communicate.
Why It Exists in Real Life
Here's the setup you'll actually see in production:
A company has four VPCs: dev, staging, prod, and shared-services. The shared-services VPC has Prometheus, Grafana, a logging stack, and a bastion host. Every other VPC needs to reach it. So you create three peering connections: dev↔shared, staging↔shared, prod↔shared.
Another scenario: microservices split across VPCs. Team A owns the payment service VPC. Team B owns the user service VPC. The payment service needs to call the user service internally. Peering gives them a private channel without either service being publicly exposed.
Acquired company scenario: Company A (on AWS) buys Company B (also on AWS). Day one, you need their inventory system to talk to your order system. You're not merging accounts yet. VPC peering is the bridge while you figure out the longer-term architecture.
How to Actually Set It Up (Where People Go Wrong)
Three steps. All three are required. Most people nail step 1, forget step 2, and then spend an hour debugging why traffic isn't flowing.
Step 1: Create and accept the peering connection
In the AWS console, go to VPC → Peering Connections → Create. You pick the requester VPC and the accepter VPC. If it's cross-account, the other account gets a request they need to manually accept. Same account, same region — you can auto-accept or accept manually.
After this step, the peering connection shows as "Active." Most people think they're done. They're not.
Step 2: Update route tables on BOTH sides
This is where everyone gets stuck.
VPC A (CIDR: 10.0.0.0/16) peered with VPC B (CIDR: 10.1.0.0/16).
In VPC A's route table, you need to add: 10.1.0.0/16 → pcx-xxxxxxxx (the peering connection ID)
In VPC B's route table, you need to add: 10.0.0.0/16 → pcx-xxxxxxxx
Both sides. If you only update one side, traffic flows one way and you get asymmetric routing issues or just silence. Update both route tables.
If your VPCs have multiple subnets, each subnet's associated route table needs the entry — not just the main route table. This catches people out constantly.
Step 3: Update security groups
Route table says where traffic should go. Security groups decide if traffic is allowed in.
Say your EC2 in VPC A wants to connect to a database in VPC B on port 5432. You've done steps 1 and 2. But the database's security group only allows inbound on 10.0.0.0/16 (VPC A's CIDR). Since the traffic is coming from VPC A's IP range, this works. But if the security group is locked down to a specific instance or a different CIDR, you'll get connection refused.
Rule: after setting up peering, check security groups on the receiving end. Add an inbound rule for the source VPC's CIDR on the required port.
The ICMP Thing (Testing Your Peering)
After you set everything up, the first thing you want to do is ping from an instance in VPC A to an instance in VPC B. Ping is the simplest network test.
Ping uses ICMP protocol — not TCP, not UDP. By default, most security groups don't allow ICMP inbound.
So if your ping times out, before you assume peering is broken, check this first: add an inbound rule to the target instance's security group for All ICMP - IPv4 from the source VPC's CIDR.
Then ping again. If it works, peering is fine — you just had ICMP blocked. If it still doesn't work, now you debug the route tables.
This saves a lot of unnecessary troubleshooting.
CIDR Overlap — Plan Before You Build
This is the most painful mistake to fix after the fact.
VPC peering requires non-overlapping CIDR blocks. If VPC A is 10.0.0.0/16 and VPC B is also 10.0.0.0/16, AWS cannot peer them. The IP ranges conflict — AWS has no way to tell whether 10.0.1.5 belongs to VPC A or VPC B.
In a small setup this is easy to avoid. In a large org where 15 teams have all defaulted to 10.0.0.0/16 over the years? It's a mess. You can't re-CIDR a VPC after creation (well, you can add secondary CIDRs, but you can't change the primary). The only real fix is tearing down and rebuilding with a new range.
The practical advice: if you're in an org that might ever need VPC peering (which is almost any org at some scale), standardize CIDR ranges from the start. A common pattern:
Shared services VPC:
10.0.0.0/16Dev VPC:
10.1.0.0/16Staging VPC:
10.2.0.0/16Prod VPC:
10.3.0.0/16
Each environment gets its own /16 block, no overlaps.
No Transitive Peering — The Limitation Nobody Mentions
A is peered with B. B is peered with C. Can A talk to C through B?
No. VPC peering is not transitive.
A → B works. B → C works. A → C does not work, even though B is in the middle. Each peering connection is a direct, bilateral link. Traffic can't "hop" through an intermediate VPC.
If A needs to reach C, you create a direct A ↔ C peering connection.
At small scale, this is fine. At large scale (10+ VPCs that all need to communicate), you end up with n(n-1)/2 peering connections. Five VPCs = 10 connections. Ten VPCs = 45 connections. It becomes unmanageable.
That's where AWS Transit Gateway comes in. It's a hub that multiple VPCs connect to — attach your VPC to the TGW once, and it can reach all other attached VPCs. Centralized routing, much simpler at scale. But that's a separate topic for a separate post.
Next up: security groups vs NACLs, and how IAM fits into all of this.
🌐 Connect with Me
💼 LinkedIn: https://linkedin.com/in/heyyprakhar1
💻 GitHub: https://github.com/Heyyprakhar1
🌍 Portfolio: https://prakharsrivastavadevops.netlify.app






