<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Micheal Angelo</title>
    <description>The latest articles on DEV Community by Micheal Angelo (@micheal_angelo_41cea4e81a).</description>
    <link>https://dev.to/micheal_angelo_41cea4e81a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3692427%2F335051a9-3e2a-438a-8022-aff118532b01.jpg</url>
      <title>DEV Community: Micheal Angelo</title>
      <link>https://dev.to/micheal_angelo_41cea4e81a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/micheal_angelo_41cea4e81a"/>
    <language>en</language>
    <item>
      <title>From Local Development to a Production-Style Deployment: Understanding Docker, Nginx, Linux, and AWS</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Fri, 03 Jul 2026 09:38:25 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/from-local-development-to-a-production-style-deployment-understanding-docker-nginx-linux-and-aws-1e27</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/from-local-development-to-a-production-style-deployment-understanding-docker-nginx-linux-and-aws-1e27</guid>
      <description>&lt;p&gt;When I first started learning cloud computing, I assumed AWS was simply a collection of services like Amazon S3, EC2, Lambda, and DynamoDB.&lt;/p&gt;

&lt;p&gt;Over time, I realized that cloud computing is much less about memorizing services and much more about understanding how distributed applications are deployed, communicate, and operate in production.&lt;/p&gt;

&lt;p&gt;To better understand these concepts without incurring cloud costs, I built a document processing pipeline locally using &lt;strong&gt;FastAPI, Docker, Docker Compose, Floci (LocalStack), Amazon S3, Amazon SQS, DynamoDB, and Nginx&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The objective wasn't to reproduce AWS perfectly—it was to understand the architectural principles that remain the same whether an application runs on a laptop or inside an EC2 instance.&lt;/p&gt;

&lt;p&gt;The complete project is available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/release/v7.0" rel="noopener noreferrer"&gt;https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/release/v7.0&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Looking Beyond Individual AWS Services
&lt;/h1&gt;

&lt;p&gt;One realization stood out while working on this project.&lt;/p&gt;

&lt;p&gt;Learning individual services is useful, but understanding &lt;strong&gt;how they collaborate&lt;/strong&gt; is far more valuable.&lt;/p&gt;

&lt;p&gt;In production, applications are rarely a single process.&lt;/p&gt;

&lt;p&gt;Instead, they consist of multiple independent components, each responsible for a specific task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web servers&lt;/li&gt;
&lt;li&gt;Application servers&lt;/li&gt;
&lt;li&gt;Object storage&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;Message queues&lt;/li&gt;
&lt;li&gt;Background workers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding how these components communicate is what transforms cloud services from isolated tools into a complete system.&lt;/p&gt;




&lt;h1&gt;
  
  
  Thinking About the Internet
&lt;/h1&gt;

&lt;p&gt;The Internet allows computers located anywhere in the world to communicate using the TCP/IP protocol suite.&lt;/p&gt;

&lt;p&gt;Now imagine that instead of communicating with another personal computer, your browser is communicating with a Linux server running continuously inside a cloud provider's data center.&lt;/p&gt;

&lt;p&gt;That machine has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Network connectivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and behaves just like any other Linux computer.&lt;/p&gt;

&lt;p&gt;An Amazon EC2 instance is essentially one such virtual Linux machine.&lt;/p&gt;

&lt;p&gt;Deploying an application simply means copying your application onto that server and running it.&lt;/p&gt;




&lt;h1&gt;
  
  
  From Domain Name to Server
&lt;/h1&gt;

&lt;p&gt;Suppose a user visits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before any application receives the request, the browser performs a DNS lookup.&lt;/p&gt;

&lt;p&gt;DNS translates a human-readable domain name into a public IP address.&lt;/p&gt;

&lt;p&gt;Once the IP address is known, the browser establishes a connection with the destination server.&lt;/p&gt;

&lt;p&gt;This entire process happens before the application itself becomes involved.&lt;/p&gt;




&lt;h1&gt;
  
  
  IP Addresses, MAC Addresses, and NAT
&lt;/h1&gt;

&lt;p&gt;Every network packet contains important addressing information.&lt;/p&gt;

&lt;p&gt;At the network layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source IP Address&lt;/li&gt;
&lt;li&gt;Destination IP Address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the data-link layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source MAC Address&lt;/li&gt;
&lt;li&gt;Destination MAC Address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One concept that became much clearer while studying networking was that MAC addresses only exist within a local network.&lt;/p&gt;

&lt;p&gt;Packets travelling across the Internet never keep the same MAC address.&lt;/p&gt;

&lt;p&gt;Each router forwards the packet by replacing the Layer 2 addressing information while preserving the end-to-end IP addresses.&lt;/p&gt;

&lt;p&gt;Similarly, home routers perform Network Address Translation (NAT), replacing private addresses with a public address before forwarding traffic onto the Internet.&lt;/p&gt;

&lt;p&gt;Understanding these concepts made cloud networking feel much less mysterious.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Ports Exist
&lt;/h1&gt;

&lt;p&gt;Knowing the destination IP address isn't enough.&lt;/p&gt;

&lt;p&gt;A Linux server may be running many different applications simultaneously.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="m"&gt;22&lt;/span&gt;   → &lt;span class="n"&gt;SSH&lt;/span&gt;
&lt;span class="m"&gt;80&lt;/span&gt;   → &lt;span class="n"&gt;HTTP&lt;/span&gt;
&lt;span class="m"&gt;443&lt;/span&gt;  → &lt;span class="n"&gt;HTTPS&lt;/span&gt;
&lt;span class="m"&gt;5432&lt;/span&gt; → &lt;span class="n"&gt;PostgreSQL&lt;/span&gt;
&lt;span class="m"&gt;6379&lt;/span&gt; → &lt;span class="n"&gt;Redis&lt;/span&gt;
&lt;span class="m"&gt;8000&lt;/span&gt; → &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every process listens on a specific port.&lt;/p&gt;

&lt;p&gt;When packets arrive, the Linux kernel examines the destination port and forwards the request to the appropriate application.&lt;/p&gt;

&lt;p&gt;This explains why URLs such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;explicitly communicate with a FastAPI application running on port 8000.&lt;/p&gt;




&lt;h1&gt;
  
  
  Local Development
&lt;/h1&gt;

&lt;p&gt;During development, frontend and backend applications often run independently.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend
↓

localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Backend
↓

localhost:8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup is convenient because developers can work on each application separately.&lt;/p&gt;

&lt;p&gt;However, exposing multiple ports directly to users becomes impractical in production.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Production Looks Different
&lt;/h1&gt;

&lt;p&gt;Imagine asking users to remember:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;example&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;:&lt;span class="m"&gt;3000&lt;/span&gt;
&lt;span class="n"&gt;example&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;:&lt;span class="m"&gt;8000&lt;/span&gt;
&lt;span class="n"&gt;example&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;:&lt;span class="m"&gt;9090&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for different services.&lt;/p&gt;

&lt;p&gt;That quickly becomes difficult to manage.&lt;/p&gt;

&lt;p&gt;Instead, production systems expose a single public entry point.&lt;/p&gt;

&lt;p&gt;This is where reverse proxies become important.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding Nginx
&lt;/h1&gt;

&lt;p&gt;One of the concepts that initially seemed confusing was the idea of a reverse proxy.&lt;/p&gt;

&lt;p&gt;Eventually, it became much simpler after realizing that Nginx is simply another Linux process listening on ports 80 and 443.&lt;/p&gt;

&lt;p&gt;Rather than exposing every application individually, only Nginx is exposed.&lt;/p&gt;

&lt;p&gt;It receives incoming requests and forwards them internally to the correct application.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
     │
     ▼
Nginx
     │
     ├────────► Frontend
     │
     └────────► FastAPI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser communicates only with Nginx.&lt;/p&gt;

&lt;p&gt;The backend applications remain hidden from direct Internet access.&lt;/p&gt;

&lt;p&gt;Besides routing requests, Nginx also centralizes configuration, improves security, and simplifies deployment.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding HTTPS
&lt;/h1&gt;

&lt;p&gt;HTTPS initially sounded like a completely different protocol.&lt;/p&gt;

&lt;p&gt;In reality, it is simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP + TLS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Certificate Authority (CA) issues a certificate for a domain after verifying ownership.&lt;/p&gt;

&lt;p&gt;That certificate is configured inside Nginx.&lt;/p&gt;

&lt;p&gt;When a browser connects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A TLS handshake occurs.&lt;/li&gt;
&lt;li&gt;The certificate is validated.&lt;/li&gt;
&lt;li&gt;Encryption keys are negotiated.&lt;/li&gt;
&lt;li&gt;HTTP communication becomes encrypted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An interesting observation is that the FastAPI application itself remains unchanged.&lt;/p&gt;

&lt;p&gt;Nginx performs TLS termination and forwards ordinary HTTP requests to the backend.&lt;/p&gt;

&lt;p&gt;This separation allows backend services to focus entirely on application logic.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building the Architecture Locally
&lt;/h1&gt;

&lt;p&gt;Although the application currently runs on a local Linux machine, its architecture closely resembles a production deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
     │
     ▼
Nginx
     │
     ▼
FastAPI
     │
     ├────────► Amazon S3
     ├────────► Amazon SQS
     │                 │
     │                 ▼
     │            Background Worker
     │                 │
     ▼                 ▼
           Amazon DynamoDB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Floci made it possible to experiment with AWS-compatible services without requiring an active AWS account.&lt;/p&gt;

&lt;p&gt;The same architectural principles remain applicable when deploying to EC2.&lt;/p&gt;




&lt;h1&gt;
  
  
  Lessons Learned
&lt;/h1&gt;

&lt;p&gt;Working through this project connected many concepts that previously felt unrelated.&lt;/p&gt;

&lt;p&gt;Some of the most valuable lessons included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding Docker and Docker Compose.&lt;/li&gt;
&lt;li&gt;Building a multi-container application.&lt;/li&gt;
&lt;li&gt;Using AWS-compatible services locally through Floci.&lt;/li&gt;
&lt;li&gt;Learning event-driven architecture with Amazon SQS.&lt;/li&gt;
&lt;li&gt;Separating file storage from metadata storage.&lt;/li&gt;
&lt;li&gt;Running background workers independently from the API.&lt;/li&gt;
&lt;li&gt;Understanding Linux processes and ports.&lt;/li&gt;
&lt;li&gt;Connecting DNS, TCP/IP, NAT, and reverse proxies into one mental model.&lt;/li&gt;
&lt;li&gt;Understanding HTTPS and TLS termination.&lt;/li&gt;
&lt;li&gt;Organizing applications using production-style architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perhaps the biggest realization was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cloud computing is not just about learning cloud services. It is about understanding the systems that connect them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once those architectural principles become clear, moving the same application from a local Linux machine to an EC2 instance becomes largely a deployment exercise rather than a redesign.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;This project fundamentally changed the way I think about cloud computing.&lt;/p&gt;

&lt;p&gt;Instead of seeing AWS as a catalog of independent services, I now see it as an ecosystem where networking, Linux, containers, storage, messaging, databases, and application servers collaborate to build scalable systems.&lt;/p&gt;

&lt;p&gt;Learning these architectural principles has been far more valuable than memorizing individual services, because those principles remain applicable regardless of the cloud provider or deployment environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Repository
&lt;/h2&gt;

&lt;p&gt;The complete project is available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/release/v7.0" rel="noopener noreferrer"&gt;https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/release/v7.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback and suggestions are always welcome.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>nginx</category>
      <category>cloud</category>
      <category>networking</category>
    </item>
    <item>
      <title>From a Simple File Upload API to an Event-Driven AWS Document Processing Pipeline</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Tue, 30 Jun 2026 15:02:17 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/from-a-simple-file-upload-api-to-an-event-driven-aws-document-processing-pipeline-4i5m</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/from-a-simple-file-upload-api-to-an-event-driven-aws-document-processing-pipeline-4i5m</guid>
      <description>&lt;p&gt;When I first started learning AWS, I assumed cloud computing was mostly about understanding individual services like Amazon S3, DynamoDB, Lambda, or EC2.&lt;/p&gt;

&lt;p&gt;After spending time building a document processing pipeline locally, I realized something different.&lt;/p&gt;

&lt;p&gt;Cloud computing isn't simply a collection of services—it's about how those services collaborate to solve real engineering problems.&lt;/p&gt;

&lt;p&gt;Rather than learning each service in isolation, I gradually evolved a small FastAPI application into an event-driven, containerized backend. Along the way, I explored concepts like object storage, asynchronous processing, infrastructure automation, containerization, and continuous integration.&lt;/p&gt;

&lt;p&gt;This article summarizes that journey and, more importantly, the architectural lessons learned along the way.&lt;/p&gt;




&lt;h1&gt;
  
  
  Starting with a Simple REST API
&lt;/h1&gt;

&lt;p&gt;The project began with a straightforward goal: accept document uploads through a REST API.&lt;/p&gt;

&lt;p&gt;The initial architecture looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
FastAPI
   │
   ▼
Local Storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uploaded files were simply written to a folder on the local machine.&lt;/p&gt;

&lt;p&gt;While functional, this design tightly coupled the application to the local filesystem. The application worked only because it was running on my laptop.&lt;/p&gt;




&lt;h1&gt;
  
  
  Moving from Local Storage to Object Storage
&lt;/h1&gt;

&lt;p&gt;The first architectural improvement was replacing local storage with Amazon S3.&lt;/p&gt;

&lt;p&gt;Instead of keeping uploaded files inside the application directory, they were stored in an object storage service.&lt;/p&gt;

&lt;p&gt;The architecture became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
FastAPI
   │
   ▼
Amazon S3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This introduced one of the first important cloud concepts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Application servers shouldn't permanently own user files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Object storage provides durability, scalability, and independence from the application itself.&lt;/p&gt;




&lt;h1&gt;
  
  
  Learning AWS Without an AWS Account
&lt;/h1&gt;

&lt;p&gt;Rather than using a paid AWS account, I used &lt;strong&gt;Floci&lt;/strong&gt;, an open-source AWS emulator built on top of LocalStack.&lt;/p&gt;

&lt;p&gt;The architecture looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FastAPI
    │
    ▼
localhost:4566
    │
    ▼
Floci
    │
    ├── S3
    ├── DynamoDB
    └── SQS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application interacted with Floci using the official AWS SDK (&lt;code&gt;boto3&lt;/code&gt;), making the experience very similar to working with real AWS services.&lt;/p&gt;

&lt;p&gt;This made it possible to experiment with cloud concepts locally without worrying about cloud costs.&lt;/p&gt;




&lt;h1&gt;
  
  
  Using boto3 Instead of Raw HTTP Requests
&lt;/h1&gt;

&lt;p&gt;Applications rarely communicate with AWS services by constructing HTTP requests manually.&lt;/p&gt;

&lt;p&gt;Instead, AWS provides Software Development Kits (SDKs).&lt;/p&gt;

&lt;p&gt;In Python, this is &lt;code&gt;boto3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A simple call like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;hides a significant amount of complexity.&lt;/p&gt;

&lt;p&gt;The SDK handles authentication, request formatting, retries, and communication with AWS-compatible APIs, allowing developers to focus on application logic rather than protocol details.&lt;/p&gt;




&lt;h1&gt;
  
  
  Making Infrastructure Self-Initializing
&lt;/h1&gt;

&lt;p&gt;Initially, the application assumed that the required S3 bucket already existed.&lt;/p&gt;

&lt;p&gt;That meant manually creating resources before starting the application.&lt;/p&gt;

&lt;p&gt;Instead, startup logic was introduced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application Starts
        │
        ▼
Check Bucket
        │
 ┌──────┴──────┐
 │             │
 ▼             ▼
Exists     Create Bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This small improvement made the application much easier to run in a fresh environment and reduced manual setup.&lt;/p&gt;




&lt;h1&gt;
  
  
  Separating Files from Metadata
&lt;/h1&gt;

&lt;p&gt;Uploading files solved only part of the problem.&lt;/p&gt;

&lt;p&gt;Information about each uploaded document—such as filename, upload time, size, and a unique identifier—also needed to be stored.&lt;/p&gt;

&lt;p&gt;Instead of embedding this information within the files themselves, metadata was stored separately in Amazon DynamoDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S3
 │
 ▼
Document Files

DynamoDB
 │
 ▼
Document Metadata
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Separating binary data from structured metadata is a common design pattern in cloud-native applications.&lt;/p&gt;




&lt;h1&gt;
  
  
  Introducing Event-Driven Architecture
&lt;/h1&gt;

&lt;p&gt;Initially, the upload request handled every operation synchronously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Upload File
      │
      ▼
Store Metadata
      │
      ▼
Return Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This meant users had to wait until every task finished.&lt;/p&gt;

&lt;p&gt;To improve the design, asynchronous processing was introduced using Amazon SQS.&lt;/p&gt;

&lt;p&gt;The workflow became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
      │
      ▼
FastAPI
      │
      ▼
Upload to S3
      │
      ▼
Send Message to SQS
      │
      ▼
Return Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of doing everything immediately, the application now creates a message describing the work that still needs to be done.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Queues Matter
&lt;/h1&gt;

&lt;p&gt;Queues become especially valuable when traffic increases.&lt;/p&gt;

&lt;p&gt;Imagine thousands of users uploading documents simultaneously.&lt;/p&gt;

&lt;p&gt;Without a queue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Requests
    │
    ▼
Application
    │
    ▼
Overloaded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a queue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Requests
    │
    ▼
SQS Queue
    │
    ▼
Background Workers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The queue acts as a buffer, smoothing sudden spikes in traffic and allowing work to be processed at a sustainable pace.&lt;/p&gt;




&lt;h1&gt;
  
  
  Background Workers
&lt;/h1&gt;

&lt;p&gt;A dedicated worker continuously monitors the queue.&lt;/p&gt;

&lt;p&gt;Its responsibility is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Receive Message
      │
      ▼
Process
      │
      ▼
Store Metadata
      │
      ▼
Delete Message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Separating background processing from the API keeps responsibilities clear and allows each component to scale independently.&lt;/p&gt;




&lt;h1&gt;
  
  
  Exploring Serverless Computing
&lt;/h1&gt;

&lt;p&gt;I also experimented with AWS Lambda.&lt;/p&gt;

&lt;p&gt;Instead of running workers continuously, Lambda executes code only when an event occurs.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event
   │
   ▼
Lambda
   │
   ▼
Execute
   │
   ▼
Terminate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This introduced the idea of serverless computing, where compute resources exist only while work is being performed.&lt;/p&gt;




&lt;h1&gt;
  
  
  Containerizing the Application
&lt;/h1&gt;

&lt;p&gt;As the project grew, another challenge appeared.&lt;/p&gt;

&lt;p&gt;How could another machine run the application without manually installing Python, dependencies, or configuring the environment?&lt;/p&gt;

&lt;p&gt;Docker solved this problem.&lt;/p&gt;

&lt;p&gt;A Docker image packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;into a single portable artifact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source Code
      │
      ▼
Docker Build
      │
      ▼
Docker Image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A container is simply a running instance of that image.&lt;/p&gt;




&lt;h1&gt;
  
  
  Managing Multiple Services with Docker Compose
&lt;/h1&gt;

&lt;p&gt;Eventually, the project consisted of several independent services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Background Worker&lt;/li&gt;
&lt;li&gt;Floci&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of starting each one manually, Docker Compose orchestrated the entire environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker Compose
      │
 ┌────┼────┐
 ▼    ▼    ▼
API Worker Floci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made local development significantly more reproducible.&lt;/p&gt;




&lt;h1&gt;
  
  
  Automating Builds with GitHub Actions
&lt;/h1&gt;

&lt;p&gt;Running the application locally wasn't enough.&lt;/p&gt;

&lt;p&gt;Every code change should also be verified automatically.&lt;/p&gt;

&lt;p&gt;GitHub Actions introduced a simple CI pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Push Code
     │
     ▼
GitHub Actions
     │
     ▼
Install Dependencies
     │
     ▼
Build Docker Image
     │
     ▼
Report Status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automation helps catch problems earlier and creates confidence that the project remains buildable.&lt;/p&gt;




&lt;h1&gt;
  
  
  Sharing Images Through Docker Hub
&lt;/h1&gt;

&lt;p&gt;Docker images initially existed only on one machine.&lt;/p&gt;

&lt;p&gt;Publishing them to Docker Hub changed that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local Build
     │
     ▼
Docker Hub
     │
     ▼
Any Machine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once uploaded, the same image can be pulled and executed anywhere without rebuilding.&lt;/p&gt;

&lt;p&gt;This is the essence of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build once, run anywhere.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Looking Ahead to Deployment
&lt;/h1&gt;

&lt;p&gt;The next natural step is deployment.&lt;/p&gt;

&lt;p&gt;Instead of running the application on a personal laptop, the same Docker image can be deployed to an Amazon EC2 instance.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub
     │
     ▼
GitHub Actions
     │
     ▼
Docker Hub
     │
     ▼
EC2 Instance
     │
     ▼
Docker Compose
     │
 ┌───┼────┐
 ▼   ▼    ▼
API Worker Floci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cloud deployment becomes much simpler because the application is already packaged as a container.&lt;/p&gt;




&lt;h1&gt;
  
  
  Key Lessons Learned
&lt;/h1&gt;

&lt;p&gt;This project reinforced several important ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud computing is about systems, not isolated services.&lt;/li&gt;
&lt;li&gt;Object storage and metadata storage solve different problems.&lt;/li&gt;
&lt;li&gt;Event-driven architectures improve scalability and responsiveness.&lt;/li&gt;
&lt;li&gt;Queues decouple producers from consumers.&lt;/li&gt;
&lt;li&gt;Background workers allow long-running tasks to happen asynchronously.&lt;/li&gt;
&lt;li&gt;Containers provide consistent execution environments.&lt;/li&gt;
&lt;li&gt;Continuous Integration improves software quality.&lt;/li&gt;
&lt;li&gt;Good software engineering principles matter just as much as cloud knowledge.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Looking back, the biggest takeaway wasn't learning Amazon S3, DynamoDB, SQS, Docker, or GitHub Actions individually.&lt;/p&gt;

&lt;p&gt;It was understanding how each component contributes a single responsibility within a larger system.&lt;/p&gt;

&lt;p&gt;Cloud applications become easier to extend, maintain, and scale when responsibilities are clearly separated and services communicate through well-defined interfaces.&lt;/p&gt;

&lt;p&gt;Building this project transformed cloud computing from a list of services into a connected ecosystem of architectural patterns—and that has been one of the most valuable lessons in my learning journey.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Repository
&lt;/h2&gt;

&lt;p&gt;The complete project is available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/release/v6.0" rel="noopener noreferrer"&gt;https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/release/v6.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback and suggestions are always welcome.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>docker</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Building a Cloud Application Locally: Lessons in Backend Architecture and AWS</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Thu, 25 Jun 2026 13:07:32 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/building-a-cloud-application-locally-lessons-in-backend-architecture-and-aws-501</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/building-a-cloud-application-locally-lessons-in-backend-architecture-and-aws-501</guid>
      <description>&lt;p&gt;When learning cloud computing, it's tempting to jump straight into individual services like Amazon S3, DynamoDB, or Lambda. While understanding each service is important, I found that the bigger lesson wasn't about the services themselves—it was about &lt;strong&gt;how applications are designed to evolve over time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To explore this, I started building a document processing backend locally using &lt;strong&gt;FastAPI&lt;/strong&gt;, &lt;strong&gt;Floci&lt;/strong&gt; (an open-source AWS emulator), &lt;strong&gt;Docker&lt;/strong&gt;, and &lt;strong&gt;boto3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What began as a simple file upload endpoint gradually evolved into a small document management backend capable of uploading, listing, downloading, and deleting documents while keeping the application architecture modular.&lt;/p&gt;

&lt;p&gt;The goal wasn't just to interact with AWS services. It was to understand how good backend design allows applications to grow without requiring major rewrites.&lt;/p&gt;




&lt;h1&gt;
  
  
  Starting Simple
&lt;/h1&gt;

&lt;p&gt;The application originally had a single responsibility:&lt;/p&gt;

&lt;p&gt;Accept a document through an API.&lt;/p&gt;

&lt;p&gt;The initial architecture was straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
FastAPI
   │
   ▼
uploads/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uploaded files were simply written to a local directory.&lt;/p&gt;

&lt;p&gt;Although this worked, the API endpoint became tightly coupled to the storage implementation.&lt;/p&gt;

&lt;p&gt;Changing the storage mechanism later would require modifying the route itself.&lt;/p&gt;




&lt;h1&gt;
  
  
  Introducing a Service Layer
&lt;/h1&gt;

&lt;p&gt;To reduce that coupling, the storage logic was extracted into a dedicated service.&lt;/p&gt;

&lt;p&gt;The architecture became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
FastAPI
   │
   ▼
Storage Service
   │
   ▼
Local Storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the application's behavior remained the same, this introduced an important software engineering principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Separation of Concerns.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The API became responsible for handling HTTP requests.&lt;/p&gt;

&lt;p&gt;The storage service became responsible for managing files.&lt;/p&gt;




&lt;h1&gt;
  
  
  Swapping Local Storage for Amazon S3
&lt;/h1&gt;

&lt;p&gt;Once the storage logic was isolated, replacing the implementation became surprisingly simple.&lt;/p&gt;

&lt;p&gt;Instead of saving files locally, the storage service was updated to use Amazon S3 through the AWS SDK (&lt;code&gt;boto3&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The architecture changed to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
   │
   ▼
FastAPI
   │
   ▼
S3 Storage Service
   │
   ▼
Amazon S3 (Floci)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API endpoints themselves didn't need to change.&lt;/p&gt;

&lt;p&gt;Only the storage implementation changed.&lt;/p&gt;

&lt;p&gt;That was one of the biggest takeaways from this project.&lt;/p&gt;




&lt;h1&gt;
  
  
  Making Infrastructure Self-Initializing
&lt;/h1&gt;

&lt;p&gt;Another improvement was avoiding manual infrastructure setup.&lt;/p&gt;

&lt;p&gt;Rather than assuming the S3 bucket already existed, the application now checks for it during startup and creates it if necessary.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application Starts
        │
        ▼
Check Bucket
        │
        ▼
Create If Missing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the application easier to run on a fresh machine and reduces manual setup.&lt;/p&gt;




&lt;h1&gt;
  
  
  Evolving Beyond File Uploads
&lt;/h1&gt;

&lt;p&gt;Initially, the project focused only on uploading files.&lt;/p&gt;

&lt;p&gt;As development progressed, it evolved into a small document management backend.&lt;/p&gt;

&lt;p&gt;The application now supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uploading documents&lt;/li&gt;
&lt;li&gt;Listing stored documents&lt;/li&gt;
&lt;li&gt;Downloading documents&lt;/li&gt;
&lt;li&gt;Deleting documents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current API exposes endpoints such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /upload&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /documents&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /download/{filename}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /documents/{filename}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One realization stood out during this stage:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good architecture doesn't eliminate future changes—it makes future changes easier to implement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because storage logic was already isolated behind a service layer, adding new endpoints required very little modification to the existing code.&lt;/p&gt;




&lt;h1&gt;
  
  
  Adding DynamoDB
&lt;/h1&gt;

&lt;p&gt;Managing files solved only part of the problem.&lt;/p&gt;

&lt;p&gt;Applications also need to manage information &lt;em&gt;about&lt;/em&gt; those files.&lt;/p&gt;

&lt;p&gt;To prepare for that, a dedicated DynamoDB service was introduced.&lt;/p&gt;

&lt;p&gt;Its responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating unique document identifiers&lt;/li&gt;
&lt;li&gt;Recording upload timestamps&lt;/li&gt;
&lt;li&gt;Managing document metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Client
                    │
        ┌───────────┴───────────┐
        ▼                       ▼
 Upload / Download        List / Delete
        │                       │
        └───────────┬───────────┘
                    ▼
                FastAPI
            ┌───────┴────────┐
            ▼                ▼
      S3 Storage        DynamoDB Service
            ▼                ▼
      Amazon S3       Amazon DynamoDB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the moment, document storage is fully functional, while the DynamoDB service provides the foundation for future metadata management.&lt;/p&gt;




&lt;h1&gt;
  
  
  More Than Learning AWS
&lt;/h1&gt;

&lt;p&gt;Although the project uses services like Amazon S3 and DynamoDB, the most valuable lessons weren't AWS-specific.&lt;/p&gt;

&lt;p&gt;It reinforced several software engineering concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separation of Concerns&lt;/li&gt;
&lt;li&gt;Service Layer Pattern&lt;/li&gt;
&lt;li&gt;Dependency Isolation&lt;/li&gt;
&lt;li&gt;Infrastructure Initialization&lt;/li&gt;
&lt;li&gt;Modular Backend Design&lt;/li&gt;
&lt;li&gt;Storage Abstraction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These ideas apply regardless of whether the backend eventually uses Amazon S3, Azure Blob Storage, Google Cloud Storage, or even a local filesystem.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Bigger Lesson
&lt;/h1&gt;

&lt;p&gt;One realization stood out throughout this project:&lt;/p&gt;

&lt;p&gt;Cloud engineering isn't just about learning cloud services.&lt;/p&gt;

&lt;p&gt;It's about designing applications that can evolve as requirements change.&lt;/p&gt;

&lt;p&gt;The project started as a simple upload endpoint.&lt;/p&gt;

&lt;p&gt;Over time it gained support for listing, downloading, and deleting documents without requiring a redesign of the application.&lt;/p&gt;

&lt;p&gt;That flexibility came from separating responsibilities early rather than tightly coupling implementation details together.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local Storage
        │
        ▼
Amazon S3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API doesn't need to know which implementation is being used.&lt;/p&gt;

&lt;p&gt;As long as the interface remains consistent, the underlying storage mechanism can evolve independently.&lt;/p&gt;

&lt;p&gt;That flexibility is what makes production systems easier to extend, test, and maintain.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Building applications has been one of the most effective ways for me to learn cloud engineering.&lt;/p&gt;

&lt;p&gt;Working through real architectural decisions made concepts like Amazon S3, DynamoDB, and the AWS SDK feel much more intuitive than simply reading documentation.&lt;/p&gt;

&lt;p&gt;More importantly, this project reinforced that good cloud applications are built not just on cloud services, but on sound software engineering principles.&lt;/p&gt;

&lt;p&gt;The cloud services may change over time.&lt;/p&gt;

&lt;p&gt;A well-designed architecture makes those changes far less painful.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Repository
&lt;/h2&gt;

&lt;p&gt;The complete project is available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/Document_Processing_Pipeline" rel="noopener noreferrer"&gt;https://github.com/micheal000010000-hub/aws-document-processing-pipeline/tree/Document_Processing_Pipeline&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, suggestions, and contributions are always welcome.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>backend</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Learning AWS by Building a Local Document Processing Pipeline (Without an AWS Account)</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Thu, 25 Jun 2026 08:23:48 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/learning-aws-by-building-a-local-document-processing-pipeline-without-an-aws-account-4k25</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/learning-aws-by-building-a-local-document-processing-pipeline-without-an-aws-account-4k25</guid>
      <description>&lt;p&gt;Cloud computing often feels difficult to learn because many tutorials focus on individual services in isolation.&lt;/p&gt;

&lt;p&gt;You create an S3 bucket in one tutorial, invoke a Lambda function in another, and experiment with DynamoDB somewhere else. While each service makes sense individually, it can still be hard to understand how they work together in a real application.&lt;/p&gt;

&lt;p&gt;Instead of learning services one by one, I wanted to build something that connected them together.&lt;/p&gt;

&lt;p&gt;Even better, I wanted to do it &lt;strong&gt;without creating an AWS account or worrying about cloud costs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Floci&lt;/strong&gt;, an open-source AWS emulator, came in.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Goal
&lt;/h1&gt;

&lt;p&gt;The objective wasn't to recreate AWS perfectly.&lt;/p&gt;

&lt;p&gt;It was to understand the interaction between services by building a simple document processing pipeline.&lt;/p&gt;

&lt;p&gt;The architecture looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
   │
   ▼
Upload Document
   │
   ▼
Amazon S3
   │
   ▼
AWS Lambda
   │
Extract Metadata
   │
   ▼
Amazon DynamoDB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the final automatic Lambda → DynamoDB write couldn't be completed due to a networking limitation inside Floci, the overall architecture mirrors how the same workflow would be built on AWS.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Learn AWS Locally?
&lt;/h1&gt;

&lt;p&gt;Running AWS services locally offers several advantages while learning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No cloud costs&lt;/li&gt;
&lt;li&gt;Safe experimentation&lt;/li&gt;
&lt;li&gt;Fast iteration&lt;/li&gt;
&lt;li&gt;Ability to inspect every component&lt;/li&gt;
&lt;li&gt;Easy debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the AWS CLI against a local endpoint also helped reinforce an important idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The AWS CLI is simply a client that sends API requests. Whether those requests go to Amazon's cloud or a local emulator depends on the configured endpoint.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  What Each Service Taught Me
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Amazon S3
&lt;/h2&gt;

&lt;p&gt;The first service I explored was Amazon S3.&lt;/p&gt;

&lt;p&gt;Rather than thinking of S3 as "cloud storage," it became much easier to understand it as &lt;strong&gt;object storage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A bucket acts as a container, while every uploaded file is stored as an object.&lt;/p&gt;

&lt;p&gt;Practical exercises included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating buckets&lt;/li&gt;
&lt;li&gt;Uploading files&lt;/li&gt;
&lt;li&gt;Listing bucket contents&lt;/li&gt;
&lt;li&gt;Downloading objects&lt;/li&gt;
&lt;li&gt;Deleting objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These simple operations clarified how applications persist documents before any further processing occurs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Amazon DynamoDB
&lt;/h2&gt;

&lt;p&gt;Once files could be stored, the next step was understanding structured data.&lt;/p&gt;

&lt;p&gt;Unlike S3, DynamoDB doesn't store files—it stores records.&lt;/p&gt;

&lt;p&gt;Creating tables, inserting items, retrieving data, and scanning tables helped reinforce the difference between object storage and NoSQL databases.&lt;/p&gt;

&lt;p&gt;Instead of storing the document itself, DynamoDB became the place to store information &lt;em&gt;about&lt;/em&gt; the document.&lt;/p&gt;




&lt;h2&gt;
  
  
  AWS Lambda
&lt;/h2&gt;

&lt;p&gt;Lambda introduced a completely different mindset.&lt;/p&gt;

&lt;p&gt;Instead of managing servers, code is packaged and uploaded as a deployment artifact.&lt;/p&gt;

&lt;p&gt;The Lambda function processed uploaded documents and generated metadata such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Document ID&lt;/li&gt;
&lt;li&gt;Filename&lt;/li&gt;
&lt;li&gt;File size&lt;/li&gt;
&lt;li&gt;Upload timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was also where I encountered some of the most interesting debugging challenges.&lt;/p&gt;




&lt;h1&gt;
  
  
  Debugging Was the Real Teacher
&lt;/h1&gt;

&lt;p&gt;Building the project wasn't just about writing code.&lt;/p&gt;

&lt;p&gt;It involved understanding how different environments interact.&lt;/p&gt;

&lt;p&gt;Some issues I encountered included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing AWS CLI inside the Lambda runtime&lt;/li&gt;
&lt;li&gt;Updating deployment packages correctly&lt;/li&gt;
&lt;li&gt;Lambda timeout while communicating with DynamoDB&lt;/li&gt;
&lt;li&gt;Docker networking behaviour inside Floci&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each issue forced me to understand the difference between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My Linux machine&lt;/li&gt;
&lt;li&gt;Docker containers&lt;/li&gt;
&lt;li&gt;Lambda runtime environments&lt;/li&gt;
&lt;li&gt;AWS SDK (&lt;code&gt;boto3&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those distinctions aren't always obvious from documentation alone, but debugging made them much clearer.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding IAM
&lt;/h1&gt;

&lt;p&gt;IAM was another concept that became easier through practice.&lt;/p&gt;

&lt;p&gt;Rather than viewing it as just another AWS service, I started thinking of IAM as the system that answers three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Who is making the request?&lt;/li&gt;
&lt;li&gt;What action is being performed?&lt;/li&gt;
&lt;li&gt;Is that action allowed?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Learning about users, groups, policies, and roles also clarified why Lambda functions execute with an IAM role instead of inheriting permissions automatically.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Bigger Picture
&lt;/h1&gt;

&lt;p&gt;One realization stood out throughout the project:&lt;/p&gt;

&lt;p&gt;AWS services don't communicate because they're "inside AWS."&lt;/p&gt;

&lt;p&gt;They communicate through well-defined APIs.&lt;/p&gt;

&lt;p&gt;Whether the services are running in Amazon's cloud or emulated locally, the interaction model remains largely the same.&lt;/p&gt;

&lt;p&gt;Understanding those interactions felt much more valuable than memorizing individual commands.&lt;/p&gt;




&lt;h1&gt;
  
  
  What This Project Reinforced
&lt;/h1&gt;

&lt;p&gt;Working through this pipeline reinforced several ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building teaches more than reading documentation.&lt;/li&gt;
&lt;li&gt;Debugging is part of learning cloud computing.&lt;/li&gt;
&lt;li&gt;IAM is fundamentally about identities and permissions.&lt;/li&gt;
&lt;li&gt;Lambda runs inside an isolated execution environment.&lt;/li&gt;
&lt;li&gt;Cloud services are loosely coupled and communicate through APIs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Cloud computing can seem overwhelming because of the sheer number of services available.&lt;/p&gt;

&lt;p&gt;Building even a small end-to-end workflow makes those services feel much less abstract.&lt;/p&gt;

&lt;p&gt;By connecting object storage, serverless compute, databases, and identity management into a single project, I gained a much clearer understanding of how these pieces fit together.&lt;/p&gt;

&lt;p&gt;For anyone beginning their cloud journey, building a small pipeline—even locally—can often teach far more than reading documentation alone.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you'd like to explore the project or contribute, here's the repository:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/micheal000010000-hub/aws-document-processing-pipeline" rel="noopener noreferrer"&gt;https://github.com/micheal000010000-hub/aws-document-processing-pipeline&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Feedback, suggestions, and contributions are always welcome.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>Learning AWS Without an AWS Account: Running S3, DynamoDB, and Lambda Locally</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Sun, 21 Jun 2026 01:38:07 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/learning-aws-without-an-aws-account-running-s3-dynamodb-and-lambda-locally-27bb</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/learning-aws-without-an-aws-account-running-s3-dynamodb-and-lambda-locally-27bb</guid>
      <description>&lt;h1&gt;
  
  
  Learning AWS Without an AWS Account: Running S3, DynamoDB, and Lambda Locally
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Image: Local AWS architecture using Floci, Docker, and AWS CLI.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a long time, I approached AWS the same way many beginners do.&lt;/p&gt;

&lt;p&gt;I would read documentation, watch tutorials, and try to memorize services.&lt;/p&gt;

&lt;p&gt;The problem was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reading about cloud services is very different from actually using them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the same time, I didn't want to create resources in a cloud account while learning basic concepts.&lt;/p&gt;

&lt;p&gt;So I started looking for a way to experiment locally.&lt;/p&gt;

&lt;p&gt;That's how I came across &lt;strong&gt;Floci&lt;/strong&gt;, an open-source AWS emulator that exposes AWS-compatible APIs on a local machine.&lt;/p&gt;

&lt;p&gt;The idea is surprisingly simple:&lt;/p&gt;

&lt;p&gt;Instead of sending requests to AWS, send them to a local container that behaves like AWS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Learn AWS Locally?
&lt;/h2&gt;

&lt;p&gt;When learning cloud concepts, most beginners want to answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is S3 really used for?&lt;/li&gt;
&lt;li&gt;How does DynamoDB store data?&lt;/li&gt;
&lt;li&gt;What does Lambda actually execute?&lt;/li&gt;
&lt;li&gt;What role does AWS CLI play?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions are easier to answer by creating resources than by reading definitions.&lt;/p&gt;

&lt;p&gt;Local emulation makes that possible without worrying about cloud costs.&lt;/p&gt;




&lt;h2&gt;
  
  
  High-Level Architecture
&lt;/h2&gt;

&lt;p&gt;The setup looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS CLI
    ↓
localhost:4566
    ↓
Floci Container
    ├── S3 Emulator
    ├── DynamoDB Emulator
    └── Lambda Emulator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of communicating with AWS infrastructure, AWS CLI communicates with Floci running on the local machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpjxnlu1nv0e5iuzqffhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpjxnlu1nv0e5iuzqffhj.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Running Floci with Docker
&lt;/h2&gt;

&lt;p&gt;The first step was starting the emulator.&lt;/p&gt;

&lt;p&gt;A simple Docker Compose configuration was enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;floci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;floci/floci:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4566:4566"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port &lt;code&gt;4566&lt;/code&gt; became the endpoint through which AWS CLI communicated with Floci.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding AWS CLI
&lt;/h2&gt;

&lt;p&gt;AWS CLI stands for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon Web Services Command Line Interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It acts as a client that converts commands into AWS API requests.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be viewed conceptually as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS CLI
     ↓
AWS API Request
     ↓
S3 Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normally those requests go to AWS.&lt;/p&gt;

&lt;p&gt;With Floci, the destination changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells AWS CLI to communicate with the local emulator instead.&lt;/p&gt;




&lt;h2&gt;
  
  
  Learning S3
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Is S3?
&lt;/h3&gt;

&lt;p&gt;S3 is an object storage service.&lt;/p&gt;

&lt;p&gt;A useful mental model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bucket
 ├── resume.pdf
 ├── image.png
 └── hello.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A bucket acts as a container.&lt;/p&gt;

&lt;p&gt;Everything stored inside it is called an object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe5f6w1uf2k0wb45pjizy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe5f6w1uf2k0wb45pjizy.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Creating a Bucket
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
s3 mb s3://notes-app-bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Uploading a File
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello from AWS Learning"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hello.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
s3 &lt;span class="nb"&gt;cp &lt;/span&gt;hello.txt s3://notes-app-bucket/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Listing Objects
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
s3 &lt;span class="nb"&gt;ls &lt;/span&gt;s3://notes-app-bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Downloading an Object
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
s3 &lt;span class="nb"&gt;cp &lt;/span&gt;s3://notes-app-bucket/hello.txt &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Key Insight
&lt;/h3&gt;

&lt;p&gt;S3 stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Videos&lt;/li&gt;
&lt;li&gt;Documents&lt;/li&gt;
&lt;li&gt;Backups&lt;/li&gt;
&lt;li&gt;Application assets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;S3 is not a database.&lt;/p&gt;

&lt;p&gt;It is object storage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Learning DynamoDB
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Is DynamoDB?
&lt;/h3&gt;

&lt;p&gt;DynamoDB is a NoSQL database service.&lt;/p&gt;

&lt;p&gt;Instead of storing files, it stores records.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"noteId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learning AWS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Today I learned S3"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fes2s2spfkiobf71rc98v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fes2s2spfkiobf71rc98v.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Creating a Table
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
dynamodb create-table &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--table-name&lt;/span&gt; Notes &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--attribute-definitions&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noteId,AttributeType&lt;span class="o"&gt;=&lt;/span&gt;S &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--key-schema&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noteId,KeyType&lt;span class="o"&gt;=&lt;/span&gt;HASH &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--billing-mode&lt;/span&gt; PAY_PER_REQUEST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Inserting Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
dynamodb put-item &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--table-name&lt;/span&gt; Notes &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--item&lt;/span&gt; &lt;span class="s1"&gt;'{
  "noteId":{"S":"1"},
  "title":{"S":"Learning AWS"},
  "content":{"S":"Today I learned S3 and DynamoDB"}
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Retrieving Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
dynamodb get-item &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--table-name&lt;/span&gt; Notes &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s1"&gt;'{"noteId":{"S":"1"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Key Insight
&lt;/h3&gt;

&lt;p&gt;A useful distinction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S3
 ↓
Stores Files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;versus&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DynamoDB
 ↓
Stores Records
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding this difference made both services much easier to reason about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Learning Lambda
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Is Lambda?
&lt;/h3&gt;

&lt;p&gt;Lambda is a serverless compute service.&lt;/p&gt;

&lt;p&gt;Unlike S3 or DynamoDB, Lambda does not primarily store data.&lt;/p&gt;

&lt;p&gt;Its job is to execute code.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from Lambda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;[Insert Figure 4: Lambda Execution Flow Here]&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Packaging the Function
&lt;/h3&gt;

&lt;p&gt;Lambda expects a deployment artifact.&lt;/p&gt;

&lt;p&gt;The simplest option is a ZIP file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zip &lt;span class="k"&gt;function&lt;/span&gt;.zip handler.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ZIP package contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application code&lt;/li&gt;
&lt;li&gt;Supporting files&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Creating the Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
lambda create-function &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--function-name&lt;/span&gt; HelloLambda &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--runtime&lt;/span&gt; python3.11 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--handler&lt;/span&gt; handler.lambda_handler &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://function.zip &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--role&lt;/span&gt; arn:aws:iam::000000000000:role/lambda-role
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  The First Failure
&lt;/h3&gt;

&lt;p&gt;The first invocation failed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to start Lambda container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This turned out to be a Docker issue.&lt;/p&gt;

&lt;p&gt;Lambda execution inside Floci relies on runtime containers.&lt;/p&gt;

&lt;p&gt;Floci needed access to Docker itself.&lt;/p&gt;




&lt;h3&gt;
  
  
  Fixing the Issue
&lt;/h3&gt;

&lt;p&gt;The solution was mounting Docker's socket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;floci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;floci/floci:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4566:4566"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once Floci could communicate with Docker, Lambda executed successfully.&lt;/p&gt;




&lt;h3&gt;
  
  
  Invoking Lambda
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 &lt;span class="se"&gt;\&lt;/span&gt;
lambda invoke &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--function-name&lt;/span&gt; HelloLambda &lt;span class="se"&gt;\&lt;/span&gt;
response.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from Lambda"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  A Brief Note on IAM
&lt;/h2&gt;

&lt;p&gt;One interesting observation was that Lambda creation succeeded even though no real IAM role was created.&lt;/p&gt;

&lt;p&gt;The emulator is intentionally more forgiving than AWS.&lt;/p&gt;

&lt;p&gt;In real AWS, IAM is responsible for controlling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who can access resources&lt;/li&gt;
&lt;li&gt;Which actions are allowed&lt;/li&gt;
&lt;li&gt;Which services can communicate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Lambda execution role acts as the identity under which the function runs.&lt;/p&gt;

&lt;p&gt;Even simple functions require one because AWS needs to know what permissions the function should have if it later interacts with services such as S3 or DynamoDB.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Exercise Taught Me
&lt;/h2&gt;

&lt;p&gt;By the end of the experiment, the following concepts became much clearer:&lt;/p&gt;

&lt;h3&gt;
  
  
  S3
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creating buckets&lt;/li&gt;
&lt;li&gt;Uploading objects&lt;/li&gt;
&lt;li&gt;Downloading objects&lt;/li&gt;
&lt;li&gt;Listing objects&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DynamoDB
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creating tables&lt;/li&gt;
&lt;li&gt;Inserting records&lt;/li&gt;
&lt;li&gt;Querying records&lt;/li&gt;
&lt;li&gt;Understanding primary keys&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lambda
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Packaging code&lt;/li&gt;
&lt;li&gt;Deploying functions&lt;/li&gt;
&lt;li&gt;Executing code&lt;/li&gt;
&lt;li&gt;Troubleshooting runtime issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Infrastructure Concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker containers&lt;/li&gt;
&lt;li&gt;Service emulation&lt;/li&gt;
&lt;li&gt;Runtime environments&lt;/li&gt;
&lt;li&gt;Deployment artifacts&lt;/li&gt;
&lt;li&gt;IAM fundamentals&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Mental Model
&lt;/h2&gt;

&lt;p&gt;When I started, S3, DynamoDB, and Lambda felt like unrelated AWS services.&lt;/p&gt;

&lt;p&gt;After running them locally, a much simpler mental model emerged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS CLI
     ↓
Floci
     ├── S3       → Stores Files
     ├── DynamoDB → Stores Records
     └── Lambda   → Runs Code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the fastest way to understand cloud services isn't reading more documentation.&lt;/p&gt;

&lt;p&gt;It's building a small environment, creating resources, breaking things, fixing them, and observing how the pieces fit together.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>From Home Networking to Enterprise Networking: What Changes Behind the Scenes?</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Sat, 20 Jun 2026 07:26:15 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/from-home-networking-to-enterprise-networking-what-changes-behind-the-scenes-1h6l</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/from-home-networking-to-enterprise-networking-what-changes-behind-the-scenes-1h6l</guid>
      <description>&lt;h1&gt;
  
  
  From Home Networking to Enterprise Networking: What Changes Behind the Scenes?
&lt;/h1&gt;

&lt;p&gt;For a long time, networking felt relatively straightforward.&lt;/p&gt;

&lt;p&gt;A device connects to a router, the router connects to the Internet, and traffic eventually reaches its destination.&lt;/p&gt;

&lt;p&gt;A simplified view looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Router
   ↓
ISP
   ↓
Internet
   ↓
Website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While studying networking, I became curious about how enterprise environments work.&lt;/p&gt;

&lt;p&gt;Corporate devices often have additional security software installed, VPN clients are common, and traffic sometimes appears to follow entirely different paths than it does on a home network.&lt;/p&gt;

&lt;p&gt;This raised an interesting question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What actually changes when networking moves from a home environment to an enterprise environment?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem Organizations Are Trying To Solve
&lt;/h2&gt;

&lt;p&gt;Home networks are usually optimized for convenience.&lt;/p&gt;

&lt;p&gt;Enterprise networks have a different set of priorities.&lt;/p&gt;

&lt;p&gt;Organizations need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protect sensitive information&lt;/li&gt;
&lt;li&gt;Restrict access to certain websites&lt;/li&gt;
&lt;li&gt;Monitor traffic for security threats&lt;/li&gt;
&lt;li&gt;Enforce compliance requirements&lt;/li&gt;
&lt;li&gt;Control how applications communicate&lt;/li&gt;
&lt;li&gt;Route traffic through approved paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simply allowing devices to communicate directly with the Internet is often insufficient.&lt;/p&gt;

&lt;p&gt;Additional security layers are introduced to enforce these requirements.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvipjbbxeuw7suailq5vd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvipjbbxeuw7suailq5vd.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is A Secure Web Gateway?
&lt;/h2&gt;

&lt;p&gt;One common component in enterprise environments is a &lt;strong&gt;Secure Web Gateway (SWG)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of traffic flowing directly to the Internet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
   ↓
Internet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;traffic may follow a path like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
   ↓
Security Client
   ↓
Secure Web Gateway
   ↓
Internet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gateway acts as an intermediary.&lt;/p&gt;

&lt;p&gt;Before traffic reaches its destination, the gateway can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply security policies&lt;/li&gt;
&lt;li&gt;Filter websites&lt;/li&gt;
&lt;li&gt;Inspect requests&lt;/li&gt;
&lt;li&gt;Generate logs&lt;/li&gt;
&lt;li&gt;Enforce compliance requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The user still experiences a normal browsing session, but additional checks occur behind the scenes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Identity Matters More Than MAC Addresses
&lt;/h2&gt;

&lt;p&gt;One misconception many beginners have is that organizations identify users primarily through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MAC addresses&lt;/li&gt;
&lt;li&gt;Local IP addresses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality, enterprise environments usually rely on richer forms of identity.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication&lt;/li&gt;
&lt;li&gt;Device certificates&lt;/li&gt;
&lt;li&gt;Security agents&lt;/li&gt;
&lt;li&gt;Corporate identity providers&lt;/li&gt;
&lt;li&gt;Session information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows an organization to distinguish between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An approved corporate device&lt;/li&gt;
&lt;li&gt;A personal device&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;even when both devices are connected to the same home Wi-Fi network.&lt;/p&gt;

&lt;p&gt;The decision is often based on identity and trust rather than simply an IP address.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Traffic Steering
&lt;/h2&gt;

&lt;p&gt;One of the more interesting concepts in enterprise networking is &lt;strong&gt;traffic steering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The basic idea is simple:&lt;/p&gt;

&lt;p&gt;Different types of traffic may follow different paths.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Web Browsing
        ↓
Gateway A

Internal Applications
        ↓
Gateway B

Client Systems
        ↓
Gateway C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The path can be chosen based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User identity&lt;/li&gt;
&lt;li&gt;Application type&lt;/li&gt;
&lt;li&gt;Destination&lt;/li&gt;
&lt;li&gt;Security policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful analogy is an airport.&lt;/p&gt;

&lt;p&gt;Passengers may enter through the same building, but different groups are routed through different checkpoints depending on where they are going.&lt;/p&gt;

&lt;p&gt;Enterprise networks often work in a similar way.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F465zojyh2alezlpe89c1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F465zojyh2alezlpe89c1.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Network Behavior Can Change Over Time
&lt;/h2&gt;

&lt;p&gt;One observation that initially confused me was that network behavior sometimes changes without any visible action from the user.&lt;/p&gt;

&lt;p&gt;A website that was inaccessible one day may suddenly become accessible later.&lt;/p&gt;

&lt;p&gt;This often happens because enterprise security platforms periodically receive updated policies.&lt;/p&gt;

&lt;p&gt;Those policies may modify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access permissions&lt;/li&gt;
&lt;li&gt;Routing behavior&lt;/li&gt;
&lt;li&gt;Security controls&lt;/li&gt;
&lt;li&gt;Gateway selection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, the path traffic follows today may not be identical to the path it follows next month.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where VPNs Fit Into The Picture
&lt;/h2&gt;

&lt;p&gt;Before learning more about networking, I assumed traffic always followed a simple path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Router
   ↓
Internet
   ↓
Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VPNs introduce an additional layer.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Encrypted Tunnel
   ↓
VPN Gateway
   ↓
Destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The VPN gateway becomes a trusted entry point into an organization's network.&lt;/p&gt;

&lt;p&gt;Instead of communicating directly with internal resources, traffic first reaches the VPN infrastructure.&lt;/p&gt;

&lt;p&gt;From there it is forwarded according to organizational policies.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyhtm2wtsanfye7j4dm3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyhtm2wtsanfye7j4dm3r.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  One Device, Multiple IP Addresses
&lt;/h2&gt;

&lt;p&gt;Another important concept is that a device may be associated with multiple IP addresses simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local IP Address
&lt;/h3&gt;

&lt;p&gt;Assigned by the home router.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.x.x
10.x.x.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Used only inside the local network.&lt;/p&gt;




&lt;h3&gt;
  
  
  Public IP Address
&lt;/h3&gt;

&lt;p&gt;Assigned by the Internet Service Provider.&lt;/p&gt;

&lt;p&gt;This is typically what external websites see.&lt;/p&gt;




&lt;h3&gt;
  
  
  VPN Address
&lt;/h3&gt;

&lt;p&gt;Assigned by the VPN infrastructure.&lt;/p&gt;

&lt;p&gt;When connected to organizational resources, this address may be used instead of the public ISP address.&lt;/p&gt;

&lt;p&gt;Understanding these different layers helps explain why network traffic can appear differently depending on where it is observed.&lt;/p&gt;




&lt;h2&gt;
  
  
  DNS Still Plays A Critical Role
&lt;/h2&gt;

&lt;p&gt;Regardless of whether traffic is flowing through a home network or an enterprise network, DNS remains fundamental.&lt;/p&gt;

&lt;p&gt;Humans prefer names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Computers require IP addresses.&lt;/p&gt;

&lt;p&gt;DNS performs the translation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
        ↓
IP Address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One useful command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nslookup example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to observe how names are resolved into addresses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building On Earlier Networking Concepts
&lt;/h2&gt;

&lt;p&gt;While learning networking, I spent a lot of time understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ARP&lt;/li&gt;
&lt;li&gt;DHCP&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;ICMP&lt;/li&gt;
&lt;li&gt;IP&lt;/li&gt;
&lt;li&gt;MAC Addresses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These protocols solve lower-level networking problems.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;ARP asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I know the IP address. What is the MAC address?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DHCP asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What IP address should I use?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DNS asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What IP address corresponds to this domain name?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enterprise networking introduces a different set of questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who is the user?&lt;/p&gt;

&lt;p&gt;Is this device trusted?&lt;/p&gt;

&lt;p&gt;Which policy applies?&lt;/p&gt;

&lt;p&gt;Which gateway should handle this traffic?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The focus shifts from simple connectivity to identity, security, and policy enforcement.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;One thing that became clear while learning networking is that enterprise networking is not a completely different world.&lt;/p&gt;

&lt;p&gt;The same fundamentals still exist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP addresses&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;TCP/IP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What changes is the addition of security, identity, and policy layers on top of those fundamentals.&lt;/p&gt;

&lt;p&gt;The more I studied packet flows and network paths, the easier these concepts became to understand.&lt;/p&gt;

&lt;p&gt;Rather than memorizing protocols individually, it became much more useful to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where is this packet going, and why is it taking that path?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That simple question often reveals how the entire system works.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>linux</category>
      <category>cloud</category>
    </item>
    <item>
      <title>One Public IP, Many Devices: How Your Router Knows Where Replies Belong</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Sat, 13 Jun 2026 17:26:18 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/one-public-ip-many-devices-how-your-router-knows-where-replies-belong-2o30</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/one-public-ip-many-devices-how-your-router-knows-where-replies-belong-2o30</guid>
      <description>&lt;p&gt;After learning about DHCP, ARP, DNS, TCP, and NAT, I ran into a question that completely changed how I thought about home networking.&lt;/p&gt;

&lt;p&gt;I already understood the basics of NAT.&lt;/p&gt;

&lt;p&gt;My laptop might have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while my router has a public address such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router replaces the private address with its public address before sending packets to the Internet.&lt;/p&gt;

&lt;p&gt;That part made sense.&lt;/p&gt;

&lt;p&gt;But then a new question appeared.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine a home network with three devices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
192.168.1.100

Phone
192.168.1.101

Tablet
192.168.1.102
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three devices are browsing websites simultaneously.&lt;/p&gt;

&lt;p&gt;After NAT, every packet appears to originate from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To the Internet, all three devices look identical.&lt;/p&gt;

&lt;p&gt;Which raises an obvious question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When replies come back, how does the router know which device should receive them?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where ports become extremely important.&lt;/p&gt;




&lt;h2&gt;
  
  
  Think of NAT Like an Apartment Building
&lt;/h2&gt;

&lt;p&gt;Imagine a large apartment building.&lt;/p&gt;

&lt;p&gt;The building has a single address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the building are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apartment 101
Apartment 102
Apartment 103
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The public IP address is the building.&lt;/p&gt;

&lt;p&gt;The ports are the apartment numbers.&lt;/p&gt;

&lt;p&gt;Without apartment numbers, a package arriving at the building could not be delivered to the correct resident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Insert Figure 1: Apartment Building Analogy Here]&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real Example
&lt;/h2&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop:
192.168.1.100

Phone:
192.168.1.101

Router:
49.43.12.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The laptop performs a DNS lookup.&lt;/p&gt;

&lt;p&gt;Its operating system chooses a temporary source port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The packet looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP:
192.168.1.100

Source Port:
53001

Destination IP:
8.8.8.8

Destination Port:
53
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Phone Does the Same Thing
&lt;/h2&gt;

&lt;p&gt;Now the phone also performs a DNS lookup.&lt;/p&gt;

&lt;p&gt;It chooses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as well.&lt;/p&gt;

&lt;p&gt;The packet becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP:
192.168.1.101

Source Port:
53001

Destination IP:
8.8.8.8

Destination Port:
53
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance this looks problematic.&lt;/p&gt;

&lt;p&gt;Both devices chose the same source port.&lt;/p&gt;

&lt;p&gt;Surprisingly, this is completely valid.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because their source IP addresses are different.&lt;/p&gt;

&lt;p&gt;Inside the LAN they are still unique connections.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Router Receives the First Packet
&lt;/h2&gt;

&lt;p&gt;The router sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100:53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and creates a translation entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100:53001
        ↓
49.43.12.10:40001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something interesting.&lt;/p&gt;

&lt;p&gt;The router did not keep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It selected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;40001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead.&lt;/p&gt;

&lt;p&gt;This becomes the public-facing connection.&lt;/p&gt;

&lt;p&gt;The outgoing packet now looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP:
49.43.12.10

Source Port:
40001

Destination IP:
8.8.8.8

Destination Port:
53
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Router Receives the Second Packet
&lt;/h2&gt;

&lt;p&gt;Now the phone's packet arrives.&lt;/p&gt;

&lt;p&gt;The router creates another entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.101:53001
        ↓
49.43.12.10:40002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what changed.&lt;/p&gt;

&lt;p&gt;The public IP stayed the same.&lt;/p&gt;

&lt;p&gt;The public port changed.&lt;/p&gt;

&lt;p&gt;The translation table now contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100:53001
        ↓
49.43.12.10:40001

192.168.1.101:53001
        ↓
49.43.12.10:40002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This table is the real magic behind modern home networking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Insert Figure 2: PAT Translation Table Here]&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Replies Return
&lt;/h2&gt;

&lt;p&gt;Google sends a reply to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10:40001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router checks its translation table.&lt;/p&gt;

&lt;p&gt;It finds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;40001
        ↓
192.168.1.100:53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The packet is rewritten and delivered to the laptop.&lt;/p&gt;




&lt;p&gt;A second reply arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10:40002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router checks the table again.&lt;/p&gt;

&lt;p&gt;It finds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;40002
        ↓
192.168.1.101:53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The packet is forwarded to the phone.&lt;/p&gt;

&lt;p&gt;Both devices receive the correct response even though they share the same public IP address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Insert Figure 3: Reply Mapping Diagram Here]&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  This Is Actually PAT
&lt;/h2&gt;

&lt;p&gt;Most people casually refer to this process as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More specifically, what is happening here is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which stands for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Port Address Translation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another common name is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAT Overload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because many devices are sharing a single public IP address.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why PAT Is So Powerful
&lt;/h2&gt;

&lt;p&gt;A port number can range from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;65535
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides roughly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;65,000+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;possible ports.&lt;/p&gt;

&lt;p&gt;That means thousands of simultaneous connections can share the same public IP address.&lt;/p&gt;

&lt;p&gt;Without PAT, home networking as we know it would be much more difficult.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does the Router Actually Store?
&lt;/h2&gt;

&lt;p&gt;The router does not simply remember IP addresses.&lt;/p&gt;

&lt;p&gt;It maintains a connection table.&lt;/p&gt;

&lt;p&gt;A simplified entry might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inside IP:
192.168.1.100

Inside Port:
53001

Outside IP:
49.43.12.10

Outside Port:
40001

Destination IP:
8.8.8.8

Destination Port:
53
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real routers store additional information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol&lt;/li&gt;
&lt;li&gt;TCP state&lt;/li&gt;
&lt;li&gt;Timeouts&lt;/li&gt;
&lt;li&gt;Flags&lt;/li&gt;
&lt;li&gt;Session metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what allows thousands of connections to coexist simultaneously.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When the Connection Ends?
&lt;/h2&gt;

&lt;p&gt;Suppose the browser tab is closed.&lt;/p&gt;

&lt;p&gt;Eventually the TCP session terminates.&lt;/p&gt;

&lt;p&gt;The router notices.&lt;/p&gt;

&lt;p&gt;The translation entry is removed.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10:40001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes available for reuse.&lt;/p&gt;

&lt;p&gt;This process happens continuously behind the scenes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Random Incoming Traffic Gets Dropped
&lt;/h2&gt;

&lt;p&gt;Imagine a random server sends a packet to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10:45000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router checks its translation table.&lt;/p&gt;

&lt;p&gt;No matching entry exists.&lt;/p&gt;

&lt;p&gt;The router effectively says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't know who requested this connection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The packet is dropped.&lt;/p&gt;

&lt;p&gt;This behavior is one reason home routers provide a basic level of protection against unsolicited traffic.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Insight That Changed My Mental Model
&lt;/h2&gt;

&lt;p&gt;Initially I thought NAT was simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Private IP
        ↓
Public IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is only part of the story.&lt;/p&gt;

&lt;p&gt;The real magic is the translation table.&lt;/p&gt;

&lt;p&gt;The router continuously maintains mappings between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(Private IP, Private Port)
                ↔
(Public IP, Public Port)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for every active connection.&lt;/p&gt;

&lt;p&gt;That is how one public IP address can support dozens of devices and thousands of simultaneous network conversations.&lt;/p&gt;

&lt;p&gt;And once this idea clicked, ports stopped feeling like random numbers and started feeling like apartment numbers in a giant building.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>linux</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Following a Packet: What Really Happens Between Opening Your Laptop</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Sat, 13 Jun 2026 10:30:24 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/following-a-packet-what-really-happens-between-opening-your-laptop-4fc</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/following-a-packet-what-really-happens-between-opening-your-laptop-4fc</guid>
      <description>&lt;p&gt;For a long time, networking felt like a collection of unrelated acronyms.&lt;/p&gt;

&lt;p&gt;DHCP.&lt;/p&gt;

&lt;p&gt;ARP.&lt;/p&gt;

&lt;p&gt;DNS.&lt;/p&gt;

&lt;p&gt;TCP.&lt;/p&gt;

&lt;p&gt;IP.&lt;/p&gt;

&lt;p&gt;NAT.&lt;/p&gt;

&lt;p&gt;VPN.&lt;/p&gt;

&lt;p&gt;I could explain each one individually.&lt;/p&gt;

&lt;p&gt;But if someone had asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What actually happens when you open a website?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would have struggled to answer.&lt;/p&gt;

&lt;p&gt;The turning point came when I stopped learning protocols individually and started following a single packet through the network.&lt;/p&gt;

&lt;p&gt;This article follows that packet from the moment a laptop connects to Wi-Fi until a webpage finally appears in the browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before We Begin: Data, Segments, Packets, and Frames
&lt;/h2&gt;

&lt;p&gt;One of the biggest beginner misconceptions is that everything is called a packet.&lt;/p&gt;

&lt;p&gt;Technically, that is not true.&lt;/p&gt;

&lt;p&gt;As data moves through the networking stack, its name changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Layer
&lt;/h3&gt;

&lt;p&gt;The browser creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage it is simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Transport Layer
&lt;/h3&gt;

&lt;p&gt;TCP adds a header containing information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source Port&lt;/li&gt;
&lt;li&gt;Destination Port&lt;/li&gt;
&lt;li&gt;Sequence Number&lt;/li&gt;
&lt;li&gt;Acknowledgement Number&lt;/li&gt;
&lt;li&gt;Flags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TCP Header + Data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is called a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Segment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Network Layer
&lt;/h3&gt;

&lt;p&gt;IP adds another header containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source IP Address&lt;/li&gt;
&lt;li&gt;Destination IP Address&lt;/li&gt;
&lt;li&gt;TTL&lt;/li&gt;
&lt;li&gt;Protocol&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP Header + Segment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Packet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Data Link Layer
&lt;/h3&gt;

&lt;p&gt;Ethernet or Wi-Fi adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source MAC Address&lt;/li&gt;
&lt;li&gt;Destination MAC Address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ethernet Header + Packet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The final structure looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frame
└── Packet
    └── Segment
        └── Data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This process is known as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Encapsulation&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every packet on the Internet begins this way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Our Example Network
&lt;/h2&gt;

&lt;p&gt;To keep things simple, imagine the following setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laptop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC = BB:BB:BB:BB:BB:BB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Router
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LAN IP  = 192.168.1.1
LAN MAC = AA:AA:AA:AA:AA:AA
Public IP = 49.43.12.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DNS Server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Website
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
104.26.10.50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's follow the packet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Laptop Boots
&lt;/h2&gt;

&lt;p&gt;Immediately after startup, the laptop knows surprisingly little.&lt;/p&gt;

&lt;p&gt;It knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My MAC Address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it does not yet know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP Address&lt;/li&gt;
&lt;li&gt;Default Gateway&lt;/li&gt;
&lt;li&gt;DNS Server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those must be discovered.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Connecting to Wi-Fi
&lt;/h2&gt;

&lt;p&gt;The laptop successfully joins the wireless network.&lt;/p&gt;

&lt;p&gt;At this point many people assume networking is ready.&lt;/p&gt;

&lt;p&gt;It is not.&lt;/p&gt;

&lt;p&gt;The laptop still lacks an IP address.&lt;/p&gt;

&lt;p&gt;Without one, meaningful communication cannot occur.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: DHCP Gives the Laptop an Identity
&lt;/h2&gt;

&lt;p&gt;The laptop broadcasts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DHCP Discover
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meaning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is there a DHCP server available?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The router responds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DHCP Offer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP Address = 192.168.1.100
Gateway    = 192.168.1.1
DNS Server = 8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The laptop accepts.&lt;/p&gt;

&lt;p&gt;Now it finally knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who am I?
Where should I send traffic?
Which DNS server should I use?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DHCP has completed its job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: The User Opens a Website
&lt;/h2&gt;

&lt;p&gt;Suppose the user enters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser immediately faces a problem.&lt;/p&gt;

&lt;p&gt;It knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but websites are reached using IP addresses.&lt;/p&gt;

&lt;p&gt;The browser asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What IP address belongs to example.com?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5: Before DNS, ARP Happens
&lt;/h2&gt;

&lt;p&gt;To contact the DNS server, the laptop must send traffic through the router.&lt;/p&gt;

&lt;p&gt;It knows the router's IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it does not know:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Router MAC Address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it broadcasts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who has 192.168.1.1?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an ARP request.&lt;/p&gt;

&lt;p&gt;The router replies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.1 is AA:AA:AA:AA:AA:AA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The laptop stores this information in its ARP cache.&lt;/p&gt;

&lt;p&gt;Problem solved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: The DNS Query Leaves the Laptop
&lt;/h2&gt;

&lt;p&gt;The laptop creates an IP packet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP      = 192.168.1.100
Destination IP = 8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it creates a frame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source MAC      = BB:BB:BB:BB:BB:BB
Destination MAC = AA:AA:AA:AA:AA:AA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reveals an important networking principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination IP  = Final Destination

Destination MAC = Next Hop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For many beginners, this is the first surprising realization.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: NAT Changes the Source Address
&lt;/h2&gt;

&lt;p&gt;The router receives the packet.&lt;/p&gt;

&lt;p&gt;The router notices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a private IP address.&lt;/p&gt;

&lt;p&gt;Private addresses cannot travel across the public Internet.&lt;/p&gt;

&lt;p&gt;The router performs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Network Address Translation.&lt;/p&gt;

&lt;p&gt;The source address changes from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which is the router's public IP.&lt;/p&gt;

&lt;p&gt;The router also records this translation in its NAT table.&lt;/p&gt;

&lt;p&gt;This is how replies find their way back later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Routers Forward the Packet
&lt;/h2&gt;

&lt;p&gt;The packet begins traveling across the Internet.&lt;/p&gt;

&lt;p&gt;An important detail often goes unnoticed.&lt;/p&gt;

&lt;p&gt;At every hop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Old Ethernet Frame
      ↓
Discarded

New Ethernet Frame
      ↓
Created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC Addresses
Change at every hop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP Addresses
Remain largely unchanged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why networking engineers often say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC = Hop-to-Hop

IP = End-to-End
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 9: The DNS Server Responds
&lt;/h2&gt;

&lt;p&gt;Eventually the packet reaches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google DNS receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP = 49.43.12.10
Destination IP = 8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something important.&lt;/p&gt;

&lt;p&gt;Google never sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It only sees the public address created by NAT.&lt;/p&gt;

&lt;p&gt;Google replies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com = 104.26.10.50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 10: The Reply Finds Its Way Home
&lt;/h2&gt;

&lt;p&gt;The DNS reply eventually returns to the home router.&lt;/p&gt;

&lt;p&gt;The router consults its NAT table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;49.43.12.10:53001
        ↓
192.168.1.100:53001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router now knows exactly which device requested the information.&lt;/p&gt;

&lt;p&gt;The reply is forwarded back to the laptop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 11: TCP Establishes a Connection
&lt;/h2&gt;

&lt;p&gt;Now the browser finally knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com = 104.26.10.50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before sending data, TCP establishes a connection.&lt;/p&gt;

&lt;p&gt;The famous three-way handshake occurs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SYN
 ↓
SYN-ACK
 ↓
ACK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The connection is now established.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 12: TLS Creates Encryption
&lt;/h2&gt;

&lt;p&gt;Because the website uses HTTPS, encryption must be negotiated.&lt;/p&gt;

&lt;p&gt;The browser and server exchange:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certificates&lt;/li&gt;
&lt;li&gt;Cryptographic parameters&lt;/li&gt;
&lt;li&gt;Session keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An encrypted channel is created.&lt;/p&gt;

&lt;p&gt;Only after this step can secure communication begin.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 13: The Actual Website Loads
&lt;/h2&gt;

&lt;p&gt;Finally, the browser sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server responds with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The browser renders everything.&lt;/p&gt;

&lt;p&gt;The webpage appears.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Changes When a VPN Is Enabled?
&lt;/h2&gt;

&lt;p&gt;Without a VPN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
 ↓
Router
 ↓
ISP
 ↓
Website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a VPN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
 ↓
Router
 ↓
ISP
 ↓
VPN Server
 ↓
Website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router does not disappear.&lt;/p&gt;

&lt;p&gt;ARP still happens.&lt;/p&gt;

&lt;p&gt;DHCP still happens.&lt;/p&gt;

&lt;p&gt;Frames still exist.&lt;/p&gt;

&lt;p&gt;The difference is that traffic is encrypted and sent to the VPN server first.&lt;/p&gt;

&lt;p&gt;To the ISP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPN Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;appears to be the destination.&lt;/p&gt;

&lt;p&gt;The actual website remains hidden inside the encrypted tunnel.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Mental Model That Finally Helped
&lt;/h2&gt;

&lt;p&gt;Networking became easier once I stopped imagining the Internet as a single connection.&lt;/p&gt;

&lt;p&gt;Instead, I started viewing it as many small conversations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop ↔ Router

Router ↔ ISP Router

ISP Router ↔ ISP Router

ISP Router ↔ Destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each conversation uses different MAC addresses.&lt;/p&gt;

&lt;p&gt;The IP packet survives the journey.&lt;/p&gt;

&lt;p&gt;Once that idea clicked, concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DHCP&lt;/li&gt;
&lt;li&gt;ARP&lt;/li&gt;
&lt;li&gt;DNS&lt;/li&gt;
&lt;li&gt;NAT&lt;/li&gt;
&lt;li&gt;VPNs&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;Wireshark captures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;started feeling like pieces of the same puzzle instead of isolated protocols.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;For a long time, networking felt overwhelming because every protocol seemed independent.&lt;/p&gt;

&lt;p&gt;The breakthrough came when I followed a single packet from start to finish.&lt;/p&gt;

&lt;p&gt;Rather than memorizing definitions, I began asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What problem is this protocol solving right now?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Viewed through that lens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DHCP provides identity.&lt;/li&gt;
&lt;li&gt;ARP finds local devices.&lt;/li&gt;
&lt;li&gt;DNS finds destinations.&lt;/li&gt;
&lt;li&gt;NAT enables Internet access.&lt;/li&gt;
&lt;li&gt;TCP creates reliable communication.&lt;/li&gt;
&lt;li&gt;TLS secures it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And together, they make something as ordinary as loading a webpage possible.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>linux</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A URL Worked on My Work Laptop but Not My Personal Laptop — Here's What That Taught Me About VPNs, ARP, and Networking</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Sat, 13 Jun 2026 02:41:14 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/a-url-worked-on-my-work-laptop-but-not-my-personal-laptop-heres-what-that-taught-me-about-vpns-425p</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/a-url-worked-on-my-work-laptop-but-not-my-personal-laptop-heres-what-that-taught-me-about-vpns-425p</guid>
      <description>&lt;p&gt;One of the most effective ways to learn networking is to stop memorizing protocols and start investigating real problems.&lt;/p&gt;

&lt;p&gt;Recently, I encountered a situation that seemed simple at first.&lt;/p&gt;

&lt;p&gt;A newly deployed internal service was accessible from my work laptop but not from my personal laptop.&lt;/p&gt;

&lt;p&gt;A month later, the exact same URL became accessible from both devices.&lt;/p&gt;

&lt;p&gt;At first glance this looked like a permissions issue.&lt;/p&gt;

&lt;p&gt;But the more I investigated, the more networking concepts started connecting together.&lt;/p&gt;

&lt;p&gt;What began as a simple question eventually led me through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud networking&lt;/li&gt;
&lt;li&gt;VPNs&lt;/li&gt;
&lt;li&gt;Public vs private IP addresses&lt;/li&gt;
&lt;li&gt;MAC addresses&lt;/li&gt;
&lt;li&gt;ARP&lt;/li&gt;
&lt;li&gt;Ethernet frames&lt;/li&gt;
&lt;li&gt;Packet captures in Wireshark&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article summarizes the mental models that finally helped these concepts click.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Original Question
&lt;/h2&gt;

&lt;p&gt;The observation was simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Work Laptop
     ↓
URL works

Personal Laptop
     ↓
URL does not work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Work Laptop
     ↓
URL works

Personal Laptop
     ↓
URL also works
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The obvious question was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How does a server know the difference between two laptops?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both devices were connected to the same home network.&lt;/p&gt;

&lt;p&gt;Both were using the same internet connection.&lt;/p&gt;

&lt;p&gt;So what was different?&lt;/p&gt;




&lt;h2&gt;
  
  
  My First Hypothesis: Cloud Networking Rules
&lt;/h2&gt;

&lt;p&gt;My first assumption was that the answer lived inside the cloud platform.&lt;/p&gt;

&lt;p&gt;Regardless of whether a service runs on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS&lt;/li&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;GCP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;all cloud providers offer mechanisms for controlling network access.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;li&gt;Network ACLs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Azure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Network Security Groups (NSGs)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GCP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Firewall Rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The names differ.&lt;/p&gt;

&lt;p&gt;The underlying goal is the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allow traffic
Block traffic
Control who can reach a service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This led me to a hypothesis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Perhaps the service was initially restricted and later opened to a broader audience.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That explanation seemed plausible.&lt;/p&gt;

&lt;p&gt;But there was another possibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  The VPN Realization
&lt;/h2&gt;

&lt;p&gt;My work laptop regularly connects through a VPN.&lt;/p&gt;

&lt;p&gt;Specifically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GlobalProtect VPN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This changed how I thought about the problem.&lt;/p&gt;

&lt;p&gt;Without a VPN, traffic follows a path similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Home Router
   ↓
ISP
   ↓
Internet
   ↓
Destination Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a VPN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Home Router
   ↓
ISP
   ↓
VPN Gateway
   ↓
Company Network
   ↓
Destination Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This raised a new possibility.&lt;/p&gt;

&lt;p&gt;The server might not care about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Work Laptop
vs
Personal Laptop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, it might care about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Company Network
vs
Public Internet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction made much more sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding IP Addresses
&lt;/h2&gt;

&lt;p&gt;This investigation also exposed a misunderstanding I had about IP addresses.&lt;/p&gt;

&lt;p&gt;There isn't just one IP address involved.&lt;/p&gt;

&lt;p&gt;There are several.&lt;/p&gt;




&lt;h3&gt;
  
  
  Local IP Address
&lt;/h3&gt;

&lt;p&gt;Assigned by your router through DHCP.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This address exists only inside your home network.&lt;/p&gt;

&lt;p&gt;Internet servers never see it directly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Public IP Address
&lt;/h3&gt;

&lt;p&gt;Assigned by your ISP.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;103.x.x.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the address most internet services see.&lt;/p&gt;




&lt;h3&gt;
  
  
  VPN Address
&lt;/h3&gt;

&lt;p&gt;Assigned by the VPN infrastructure.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.50.x.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When connected to a VPN, company systems may see this address instead of your ISP-assigned address.&lt;/p&gt;

&lt;p&gt;This was an important realization.&lt;/p&gt;

&lt;p&gt;A server often identifies where a request is coming from based on IP addresses—not based on the physical laptop itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  The MAC Address Misconception
&lt;/h2&gt;

&lt;p&gt;Another misconception I had involved MAC addresses.&lt;/p&gt;

&lt;p&gt;Initially I assumed that remote services might somehow see the MAC address of my network card.&lt;/p&gt;

&lt;p&gt;That is not how networking works.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Happens
&lt;/h2&gt;

&lt;p&gt;Imagine traffic moving toward GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Router
   ↓
ISP Router
   ↓
More Routers
   ↓
Datacenter Router
   ↓
GitHub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At every hop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC Address
Changes

IP Address
Remains the same
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GitHub never sees the MAC address of my Wi-Fi card.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;GitHub sees my public IP address.&lt;/p&gt;

&lt;p&gt;That single insight corrected a large part of my networking mental model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where ARP Fits In
&lt;/h2&gt;

&lt;p&gt;This naturally led to another question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If devices communicate using MAC addresses locally, how does a device discover a MAC address?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ARP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Address Resolution Protocol.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem ARP Solves
&lt;/h2&gt;

&lt;p&gt;Suppose a device knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but does not know:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2c:9c:58:8b:2d:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ARP exists to bridge that gap.&lt;/p&gt;

&lt;p&gt;Its purpose is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP Address
      ↓
Find MAC Address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  An ARP Request in Plain English
&lt;/h2&gt;

&lt;p&gt;A typical ARP request looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who has 192.168.1.10?
Tell 192.168.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Translated into normal language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I am 192.168.1.1

I am looking for
192.168.1.10

Who owns that address?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ARP requests are broadcast to the entire local network.&lt;/p&gt;




&lt;h2&gt;
  
  
  The ARP Reply
&lt;/h2&gt;

&lt;p&gt;The device that owns the address responds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.10 is at
2c:9c:58:8b:2d:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meaning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I own that IP address.

Here is my MAC address.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router can now send Ethernet frames directly to the correct device.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Discovery from Wireshark
&lt;/h2&gt;

&lt;p&gt;While inspecting packets in Wireshark, I noticed something surprising.&lt;/p&gt;

&lt;p&gt;The packet structure looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frame
   ↓
Ethernet II
   ↓
ARP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what is missing.&lt;/p&gt;

&lt;p&gt;There is no:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;layer between Ethernet and ARP.&lt;/p&gt;

&lt;p&gt;This was unexpected.&lt;/p&gt;

&lt;p&gt;I initially assumed ARP worked inside IP.&lt;/p&gt;

&lt;p&gt;It does not.&lt;/p&gt;

&lt;p&gt;ARP operates alongside IP.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why ARP Has No TTL
&lt;/h2&gt;

&lt;p&gt;Another misconception involved TTL.&lt;/p&gt;

&lt;p&gt;I assumed every networking protocol contained fields such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TTL&lt;/li&gt;
&lt;li&gt;Routing information&lt;/li&gt;
&lt;li&gt;IP headers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That assumption was wrong.&lt;/p&gt;

&lt;p&gt;TTL exists because IP packets travel through routers.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laptop
   ↓
Router
   ↓
ISP
   ↓
Internet
   ↓
Destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each router decreases the TTL value.&lt;/p&gt;

&lt;p&gt;ARP packets never leave the local network.&lt;/p&gt;

&lt;p&gt;They are not routed across the internet.&lt;/p&gt;

&lt;p&gt;Because of that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No Routing
      ↓
No TTL Needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once I understood this, ARP's design suddenly made much more sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Mental Models That Finally Clicked
&lt;/h2&gt;

&lt;p&gt;After all of this investigation, several concepts became much easier to remember.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Networking
&lt;/h3&gt;

&lt;p&gt;Different names.&lt;/p&gt;

&lt;p&gt;Same networking fundamentals.&lt;/p&gt;




&lt;h3&gt;
  
  
  VPN
&lt;/h3&gt;

&lt;p&gt;Changes the route packets take.&lt;/p&gt;




&lt;h3&gt;
  
  
  IP Address
&lt;/h3&gt;

&lt;p&gt;Identifies a device across networks.&lt;/p&gt;




&lt;h3&gt;
  
  
  MAC Address
&lt;/h3&gt;

&lt;p&gt;Identifies a network interface on a local network.&lt;/p&gt;




&lt;h3&gt;
  
  
  ARP
&lt;/h3&gt;

&lt;p&gt;Answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I know the IP address. What is the MAC address?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  DHCP
&lt;/h3&gt;

&lt;p&gt;Answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I just joined the network. Which IP address should I use?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  DNS
&lt;/h3&gt;

&lt;p&gt;Answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I know the website name. Which IP address does it map to?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;What started as a simple access issue turned into a useful networking lesson.&lt;/p&gt;

&lt;p&gt;The biggest takeaway wasn't a specific protocol.&lt;/p&gt;

&lt;p&gt;It was a different way of learning.&lt;/p&gt;

&lt;p&gt;Instead of memorizing definitions, I found it far more effective to observe actual packet exchanges and then ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why did that happen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wireshark made invisible networking behavior visible.&lt;/p&gt;

&lt;p&gt;And once the packets became visible, many concepts that previously felt disconnected finally started fitting together.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>linux</category>
      <category>wireshark</category>
    </item>
    <item>
      <title>Learning DevOps from First Principles: What an EC2 Instance Actually Is</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Mon, 08 Jun 2026 03:16:19 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/learning-devops-from-first-principles-what-an-ec2-instance-actually-is-55dp</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/learning-devops-from-first-principles-what-an-ec2-instance-actually-is-55dp</guid>
      <description>&lt;p&gt;One of the first cloud concepts many people encounter while learning AWS is &lt;strong&gt;EC2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The name sounds technical.&lt;/p&gt;

&lt;p&gt;The documentation is extensive.&lt;/p&gt;

&lt;p&gt;And the number of configuration options can make it feel like something fundamentally different from a regular computer.&lt;/p&gt;

&lt;p&gt;But while trying to understand cloud computing, I found myself repeatedly coming back to a simple thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the end of the day, an EC2 instance is just another computer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That realization helped me understand cloud infrastructure much more clearly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Intimidation Factor
&lt;/h2&gt;

&lt;p&gt;When people first open the AWS console, they encounter terms such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2&lt;/li&gt;
&lt;li&gt;VPC&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;li&gt;Elastic IPs&lt;/li&gt;
&lt;li&gt;Auto Scaling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is easy to feel that cloud computing is an entirely different world.&lt;/p&gt;

&lt;p&gt;But before diving into those concepts, it helps to ask a simpler question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is an EC2 instance actually providing?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Starting with the Name
&lt;/h2&gt;

&lt;p&gt;EC2 stands for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Elastic Compute Cloud&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The important word here is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compute&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS is essentially renting computing resources.&lt;/p&gt;

&lt;p&gt;When you launch an EC2 instance, AWS allocates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;li&gt;Memory (RAM)&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Networking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to a virtual machine that you can access.&lt;/p&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are renting a computer that lives inside AWS's infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Comparing It to a Personal Computer
&lt;/h2&gt;

&lt;p&gt;Consider a typical laptop.&lt;/p&gt;

&lt;p&gt;It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A processor&lt;/li&gt;
&lt;li&gt;RAM&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;An operating system&lt;/li&gt;
&lt;li&gt;Network connectivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now consider an EC2 instance.&lt;/p&gt;

&lt;p&gt;It also contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtual CPUs&lt;/li&gt;
&lt;li&gt;RAM&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;An operating system&lt;/li&gt;
&lt;li&gt;Network connectivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The location is different.&lt;/p&gt;

&lt;p&gt;The concepts are the same.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Main Difference: Ownership
&lt;/h2&gt;

&lt;p&gt;The biggest difference is not technical.&lt;/p&gt;

&lt;p&gt;It is operational.&lt;/p&gt;

&lt;p&gt;With a personal computer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You own the hardware.&lt;/li&gt;
&lt;li&gt;The machine sits near you.&lt;/li&gt;
&lt;li&gt;You maintain it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With EC2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS owns the hardware.&lt;/li&gt;
&lt;li&gt;The machine runs in a data center.&lt;/li&gt;
&lt;li&gt;AWS manages the physical infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You only manage the virtual machine running on top of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Linux Knowledge Transfers
&lt;/h2&gt;

&lt;p&gt;This was one of the most interesting observations during my learning.&lt;/p&gt;

&lt;p&gt;If an EC2 instance runs Linux, many of the same concepts apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File permissions&lt;/li&gt;
&lt;li&gt;Processes&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Package management&lt;/li&gt;
&lt;li&gt;Networking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if you already know how to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check running processes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps aux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or inspect network interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip addr show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;those skills remain useful inside a cloud environment.&lt;/p&gt;

&lt;p&gt;The cloud does not replace Linux.&lt;/p&gt;

&lt;p&gt;It builds upon it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Networking Suddenly Matters
&lt;/h2&gt;

&lt;p&gt;A local computer often works without much thought about networking.&lt;/p&gt;

&lt;p&gt;Cloud systems are different.&lt;/p&gt;

&lt;p&gt;To access an EC2 instance, you must think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP addresses&lt;/li&gt;
&lt;li&gt;Ports&lt;/li&gt;
&lt;li&gt;Firewalls&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which traffic should be allowed in?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which traffic should be allowed out?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;become important very quickly.&lt;/p&gt;

&lt;p&gt;This is one reason networking appears so frequently in DevOps discussions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Elastic" Part
&lt;/h2&gt;

&lt;p&gt;One aspect that does make EC2 different from a personal machine is elasticity.&lt;/p&gt;

&lt;p&gt;A laptop has fixed hardware.&lt;/p&gt;

&lt;p&gt;An EC2 instance can be changed relatively easily.&lt;/p&gt;

&lt;p&gt;Need more RAM?&lt;/p&gt;

&lt;p&gt;Choose a larger instance type.&lt;/p&gt;

&lt;p&gt;Need more CPU?&lt;/p&gt;

&lt;p&gt;Launch a different instance.&lt;/p&gt;

&lt;p&gt;Need multiple servers?&lt;/p&gt;

&lt;p&gt;Create several instances.&lt;/p&gt;

&lt;p&gt;The computer remains conceptually the same.&lt;/p&gt;

&lt;p&gt;The flexibility changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Useful Mental Model
&lt;/h2&gt;

&lt;p&gt;The way I currently think about it is:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```text id="l6t4uy"&lt;br&gt;
Personal Computer&lt;br&gt;
       ↓&lt;br&gt;
Virtual Machine&lt;br&gt;
       ↓&lt;br&gt;
Cloud Virtual Machine (EC2)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


The further you move down this chain, the more infrastructure management is abstracted away.

But the underlying concepts remain familiar.

---

## Why This Perspective Helped Me

Initially, cloud services felt like hundreds of disconnected products.

But viewing EC2 as "just another computer" made many concepts easier to understand.

Instead of asking:

&amp;gt; "How does AWS work?"

I could start by asking:

&amp;gt; "How would I do this on a Linux machine?"

Often, the cloud version turns out to be an abstraction of something that already exists.

---

## Final Thoughts

Cloud computing introduces many new terms.

Some of them are genuinely new concepts.

Others are familiar ideas presented at a larger scale.

For me, EC2 became much easier to understand once I stopped thinking of it as a cloud product and started thinking of it as a computer.

A computer with CPU, RAM, storage, networking, and an operating system.

Just running somewhere else.

And sometimes, understanding a complex system begins by realizing that it may be simpler than it first appears.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>Same Hardware, Different Experience: Why Linux Feels Faster</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Mon, 08 Jun 2026 03:16:05 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/same-hardware-different-experience-why-linux-feels-faster-hih</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/same-hardware-different-experience-why-linux-feels-faster-hih</guid>
      <description>&lt;p&gt;A few weeks after switching from Windows to Linux, I noticed something interesting.&lt;/p&gt;

&lt;p&gt;The hardware had not changed.&lt;/p&gt;

&lt;p&gt;The processor was the same.&lt;/p&gt;

&lt;p&gt;The RAM was the same.&lt;/p&gt;

&lt;p&gt;The SSD was the same.&lt;/p&gt;

&lt;p&gt;And yet, the laptop felt noticeably faster.&lt;/p&gt;

&lt;p&gt;Not necessarily because applications were completing tasks dramatically quicker, but because the entire system felt more responsive.&lt;/p&gt;

&lt;p&gt;Keyboard input felt immediate.&lt;/p&gt;

&lt;p&gt;Windows opened faster.&lt;/p&gt;

&lt;p&gt;Terminal commands appeared instantly.&lt;/p&gt;

&lt;p&gt;The desktop experience felt smoother.&lt;/p&gt;

&lt;p&gt;This raised a question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can the same hardware feel different simply because the operating system changed?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I'm still learning, this is the mental model I've built so far.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hardware Didn't Change
&lt;/h2&gt;

&lt;p&gt;Consider a laptop with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AMD Ryzen processor&lt;/li&gt;
&lt;li&gt;16 GB DDR5 RAM&lt;/li&gt;
&lt;li&gt;NVMe SSD&lt;/li&gt;
&lt;li&gt;Modern integrated graphics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When switching operating systems, none of these components change.&lt;/p&gt;

&lt;p&gt;The CPU does not suddenly become faster.&lt;/p&gt;

&lt;p&gt;The RAM does not magically increase.&lt;/p&gt;

&lt;p&gt;The SSD remains identical.&lt;/p&gt;

&lt;p&gt;From a hardware perspective:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```text id="u3m9xd"&lt;br&gt;
Before → Same Hardware&lt;br&gt;
After  → Same Hardware&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


So the difference must come from somewhere else.

---

## An Operating System Is Not Just a User Interface

Many people think of an operating system primarily as the desktop they see.

But an operating system does far more than display windows and icons.

It manages:

* Memory
* CPU scheduling
* Processes
* Storage
* Networking
* Device drivers
* Background services

In other words:

&amp;gt; The operating system decides how hardware resources are used.

Two operating systems can therefore create very different experiences using the same hardware.

---

## Perceived Performance vs Raw Performance

One thing I have learned is that performance is not always about benchmarks.

A system can have excellent benchmark scores and still feel sluggish.

Why?

Because users experience responsiveness, not benchmark numbers.

Examples include:

* How quickly a window opens
* How fast a menu appears
* How responsive typing feels
* How quickly applications launch

These small interactions shape our perception of speed.

---

## Background Services Matter

Modern operating systems often run numerous services in the background.

Examples include:

* Update services
* Search indexing
* Telemetry collection
* Synchronization services
* Device management services

Many of these provide useful functionality.

However, they also consume resources.

Even when no application is actively running, background processes may still be:

* Using memory
* Accessing storage
* Performing network activity
* Scheduling CPU work

This creates a baseline level of system activity.

---

## Resource Utilization Is a Shared Budget

A useful way to think about system resources is as a shared budget.

Your laptop has finite:

* CPU cycles
* Memory
* Storage bandwidth

Every running service consumes part of that budget.

The more resources allocated to background tasks, the fewer remain available for user-facing work.

This does not necessarily mean one operating system is "better" than another.

Different operating systems make different trade-offs.

---

## Different Priorities, Different Results

One realization that helped me understand the situation is this:

Operating systems are optimized for different goals.

Some prioritize:

* Broad hardware compatibility
* Enterprise features
* Legacy application support

Others prioritize:

* Simplicity
* Minimalism
* Resource efficiency

Neither approach is inherently right or wrong.

They simply optimize for different audiences.

---

## Why Linux Often Feels Lightweight

Many Linux distributions allow users to choose exactly what they install.

Examples include:

* Desktop environments
* Services
* Background applications
* System utilities

This flexibility often results in systems that run fewer background components by default.

Consequently:

* Memory usage may be lower
* Idle CPU usage may be lower
* Disk activity may be reduced

The hardware itself has not changed.

The workload placed on it has.

---

## The Importance of Responsiveness

One thing I did not fully appreciate before switching is how much responsiveness affects the user experience.

Consider typing.

If every keypress appears immediately, the system feels fast.

If there is even a slight delay, users notice it.

The same applies to:

* Opening terminals
* Launching applications
* Switching windows

The actual difference may only be milliseconds.

Yet those milliseconds accumulate into a perception of smoothness.

---

## Why This Matters for DevOps Learning

This observation also connects back to learning DevOps.

Many cloud servers run Linux.

Understanding Linux is not only about commands and configuration files.

It is also about understanding how operating systems manage resources.

Concepts such as:

* Memory usage
* Running processes
* Service management
* System monitoring

appear repeatedly in real-world infrastructure.

The desktop experience simply provides a visible example of those concepts.

---

## A Simple Mental Model

The way I currently think about it is:



```text id="r2n6wk"
Hardware
    +
Operating System
    +
Running Workloads
    =
User Experience
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hardware is only one part of the equation.&lt;/p&gt;

&lt;p&gt;The operating system and workload distribution matter just as much.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;After switching operating systems, the hardware remained exactly the same.&lt;/p&gt;

&lt;p&gt;Yet the overall experience changed noticeably.&lt;/p&gt;

&lt;p&gt;That experience made me realize something important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Performance is not only about how powerful a machine is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is also about how efficiently its resources are used.&lt;/p&gt;

&lt;p&gt;The fastest-feeling system is not always the one with the most powerful hardware.&lt;/p&gt;

&lt;p&gt;Sometimes, it is simply the one asking the hardware to do less.&lt;/p&gt;

&lt;p&gt;And that has been one of the most interesting lessons from exploring Linux so far.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>performance</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Learning DevOps from First Principles: MAC Addresses vs IP Addresses — The Difference Finally Clicked</title>
      <dc:creator>Micheal Angelo</dc:creator>
      <pubDate>Mon, 08 Jun 2026 03:15:52 +0000</pubDate>
      <link>https://dev.to/micheal_angelo_41cea4e81a/learning-devops-from-first-principles-mac-addresses-vs-ip-addresses-the-difference-finally-3aef</link>
      <guid>https://dev.to/micheal_angelo_41cea4e81a/learning-devops-from-first-principles-mac-addresses-vs-ip-addresses-the-difference-finally-3aef</guid>
      <description>&lt;p&gt;One of the first networking concepts that confused me was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why does a computer need both a MAC address and an IP address?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first glance, they seem to solve the same problem.&lt;/p&gt;

&lt;p&gt;Both appear to identify a device.&lt;/p&gt;

&lt;p&gt;Both show up in networking tools.&lt;/p&gt;

&lt;p&gt;Both appear in packet captures.&lt;/p&gt;

&lt;p&gt;So why do we need two different addresses?&lt;/p&gt;

&lt;p&gt;While exploring Linux networking tools and Wireshark, the distinction finally started making sense.&lt;/p&gt;

&lt;p&gt;This article summarizes the mental model that helped me understand the difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Inside the Machine
&lt;/h2&gt;

&lt;p&gt;Before discussing addresses, it helps to understand where they come from.&lt;/p&gt;

&lt;p&gt;If you open a typical laptop, you will usually find components such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Battery&lt;/li&gt;
&lt;li&gt;RAM&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Processor&lt;/li&gt;
&lt;li&gt;Cooling system&lt;/li&gt;
&lt;li&gt;Network interfaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of those network interfaces is typically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Wi-Fi card&lt;/li&gt;
&lt;li&gt;An Ethernet controller&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These components are responsible for network communication.&lt;/p&gt;

&lt;p&gt;They are the parts of the machine that actually send and receive data across a network.&lt;/p&gt;




&lt;h2&gt;
  
  
  Every Network Interface Has an Identity
&lt;/h2&gt;

&lt;p&gt;A network interface needs a way to identify itself.&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;MAC address&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;A MAC address is associated with a network interface card (NIC).&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```text id="q3d9nm"&lt;br&gt;
2C:9C:58:8B:2D:7B&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Think of it as the identity of the network interface itself.

Not the operating system.

Not the browser.

Not the application.

The network hardware.

---

## What Is a MAC Address?

MAC stands for:

**Media Access Control**

A MAC address operates at the **Data Link Layer** of the OSI model.

Its primary purpose is to help devices communicate within a local network.

Examples include:

* Laptop to router
* Router to switch
* Switch to printer

In other words:

&amp;gt; MAC addresses help devices find each other on the same local network.

---

## What Is an IP Address?

An IP address serves a different purpose.

Example:



```text id="g8x4tc"
192.168.1.20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```text id="v6u7mz"&lt;br&gt;
2405:201:8000::1&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


IP addresses operate at the **Network Layer**.

Their job is to identify where a device exists within a larger network.

This allows communication beyond a single local network.

For example:

* Home network → Internet
* Office network → Cloud server
* Laptop → GitHub

---

## The Question That Helped Me

The mental model that helped me most was:

**MAC Address answers:**

&amp;gt; Which physical device on this local network should receive this data?

**IP Address answers:**

&amp;gt; Which device anywhere in the world should receive this data?

They solve related but different problems.

---

## Hardware Identity vs Logical Identity

This is where things finally clicked for me.

A MAC address is tied to a network interface.

An IP address is assigned by the network.

Think of it this way:

### MAC Address



```text id="w2l7fa"
Identity of the network hardware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  IP Address
&lt;/h3&gt;



&lt;p&gt;```text id="h5r3ek"&lt;br&gt;
Identity assigned within a network&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


One identifies the hardware.

The other identifies the location.

---

## Why Not Use Only MAC Addresses?

Initially, I wondered:

&amp;gt; Why not simply use MAC addresses everywhere?

The problem is scale.

Imagine trying to communicate with a server on another continent.

Routers across the internet cannot practically route traffic based on MAC addresses alone.

Instead:

* IP addresses handle routing across networks.
* MAC addresses handle delivery within local networks.

This division of responsibility makes networking scalable.

---

## Seeing It in Linux

One of the easiest ways to observe this is:



```bash id="j8r4np"
ip addr show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Typical output includes interfaces such as:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```text id="f2q7xs"&lt;br&gt;
lo&lt;br&gt;
eth0&lt;br&gt;
wlp2s0&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


You may also see:

### MAC Address



```text id="c9m5vn"
link/ether 2c:9c:58:8b:2d:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  IPv4 Address
&lt;/h3&gt;



&lt;p&gt;```text id="u4x6la"&lt;br&gt;
inet 192.168.1.20&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### IPv6 Address



```text id="b7p8dw"
inet6 2405:201:8000::1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Seeing both together helped reinforce that they serve different purposes.&lt;/p&gt;


&lt;h2&gt;
  
  
  Where Wireshark Made It Click
&lt;/h2&gt;

&lt;p&gt;While experimenting with Wireshark, I noticed that packets often contained both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source MAC Address&lt;/li&gt;
&lt;li&gt;Destination MAC Address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source IP Address&lt;/li&gt;
&lt;li&gt;Destination IP Address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first this felt redundant.&lt;/p&gt;

&lt;p&gt;But it eventually became clear:&lt;/p&gt;

&lt;p&gt;The packet needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP information to determine where it should go globally.&lt;/li&gt;
&lt;li&gt;MAC information to determine which device should receive it locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are necessary.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Simple Analogy
&lt;/h2&gt;

&lt;p&gt;Imagine sending a letter.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;city and street address&lt;/strong&gt; represent the IP address.&lt;/p&gt;

&lt;p&gt;They help the postal system route the letter across large distances.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;person's name on the mailbox&lt;/strong&gt; resembles the MAC address.&lt;/p&gt;

&lt;p&gt;Once the letter arrives at the correct location, it still needs to reach the correct recipient.&lt;/p&gt;

&lt;p&gt;The analogy is not perfect, but it helped me visualize the distinction.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Useful Mental Model
&lt;/h2&gt;

&lt;p&gt;The way I currently think about it is:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```text id="n8y3vk"&lt;br&gt;
IP Address&lt;br&gt;
    ↓&lt;br&gt;
Find the correct network&lt;/p&gt;

&lt;p&gt;MAC Address&lt;br&gt;
    ↓&lt;br&gt;
Find the correct device&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Together they allow communication to scale from local networks to the global internet.

---

## Why This Matters for DevOps

At first glance, MAC addresses and IP addresses seem like purely networking topics.

But they appear everywhere:

* Cloud servers
* Containers
* Virtual machines
* Kubernetes networking
* Load balancers
* VPNs

Understanding the distinction makes many higher-level networking concepts easier to grasp.

---

## Final Thoughts

For a long time, MAC addresses and IP addresses felt like two different labels describing the same thing.

They are not.

A MAC address identifies a network interface on a local network.

An IP address identifies a device's location within a larger network.

One focuses on hardware-level delivery.

The other focuses on network-level routing.

And once that distinction clicked, many networking concepts suddenly became much easier to understand.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>networking</category>
      <category>linux</category>
      <category>wireshark</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
