What Actually Happens When You Type “google.com” Into a Browser
A few days ago, as part of my AltSchool Cloud Engineering second semester project, I was handed a simple-sounding brief: deploy a basic web app (PHP) backed by a database(MySQL), on real infrastructure, with proper security, automation, and documentation. In practice, it walked me through almost every layer of what actually happens when someone visits a website and I want to break that down here, using my own project as the example.
The Setup
My architecture has two EC2 instances sitting in the same privatae space, AWS VPC:
- Web Server: running Apache and PHP
- Database Server: running MySQL
The idea is straightforward
A user’s browser talks to the web server over the internet, and the web server privately talks to the database server behind the scenes.
The user never touches the database directly, it’s not even going to be reachable from the public internet.
Here’s the diagram I ended up with:
So What Actually Happens When You Enter an IP Address?
When you type a web server’s IP address into a browser a lets say “google.com” and hit enter, a chain of things happens almost instantly:
- DNS lookup and IP addressing: DNS is literally the internet phone book, it helps the computer locate the Ip address of the domain name “google.com” you typed in. My web server has a public IPv4 address assigned by AWS, and that’s the address that gets used here.
- TCP connection: before any actual content is exchanged, your browser and my server do a “three-way handshake” (SYN, SYN-ACK, ACK) to open a reliable connection over TCP, specifically on port 80 for plain HTTP.
- HTTP request : once the connection is open, the browser sends an HTTP GET request asking for the homepage/landing page.
- The server responds : Apache on my web server receives that request, finds that “index.html” normally but in this case “index.php” is the file to serve, hands it to PHP to execute, and PHP runs the code, including reaching out to MySQL on the database server to fetch a student record.
- HTTP response: The finished HTML (now containing my name, my server’s hostname, and the student record) gets sent back to the browser, which renders it on the screen.
All of that handshake, request, database query, response, and rendering happens in a fraction of a second, which is honestly wild to actually sit and trace through instead of taking for granted.
How the Web Server Talks to the Database
The two servers communicate over their private IP addresses, not their public ones. This matters a lot for security my database server security group only accepts connections on port 3306 from the web server’s security group specifically, nothing else. No public IP can reach it. Even SSH into the database server is locked down to my own IP.
On the PHP side, the connection itself is a simple mysqli call:
php
Get Rayya’s stories in your inbox
Join Medium for free to get updates from this writer.
Where $servername is the database server's private IP. Since both servers live in the same VPC, that private network path is fast and doesn't touch the public internet at all.
Automating the Server Setup With Bash
Instead of manually typing out installation commands on the web server, I wrote a bash script that:
- Updates the package list
- Installs Apache and PHP
- Starts Apache and enables it to launch automatically on reboot
- Logs a confirmation line to /var/log/setup.log once everything succeeds
Running one script instead of five or six manual commands means the setup is repeatable and less error-prone, if I ever needed to spin up a second identical web server, I could just run the same script and get a matching environment in seconds.
The Cron Job
I also set up a cron job that runs every minute and appends the current date, time, and server uptime to /var/log/uptime.log . On its own it looks like a small thing, but it's really a stand-in for a much bigger idea: automated monitoring.
In a real production environment, you’re not going to manually check on your servers every few minutes. Automated jobs like this are how teams collect the metrics that feed dashboards, trigger alerts, and eventually get analyzed to catch problems before they become outages. A cron job logging uptime is a toy version of the exact same principle behind real monitoring stacks like Prometheus or CloudWatch.
Where a Load Balancer Would Fit In
Right now, all traffic goes straight to a single web server. That’s fine for this project, but if that one server goes down, or gets more traffic than it can handle, the whole application becomes unavailable.
This is where a load balancer would come in. Instead of the internet pointing directly at one web server, it would point at the load balancer, which then distributes incoming requests across multiple web servers behind it.
In my image 1, I’ve marked this as a “Future Deployment” a second web server and a load balancer sitting dashed, showing exactly where they’d slot into the existing flow if traffic increased.
Challenges I Ran Into
A few things tripped me up along the way, and I think they’re worth mentioning because they’re the kind of small, unglamorous problems:
- Apache kept serving the default page instead of my PHP file. Turns out Apache prioritizes index.html over index.php if both exist in the web root. Deleting the default index.html fixed it instantly.
- My architecture diagram exported blank. I’d built it with white text and lines against draw.io’s dark canvas, and exported it as a transparent PNG which made everything invisible once viewed against a white background. Switching to a plain white background (or exporting as JPEG) solved it.
None of these were complicated fixes once I understood what was going on.
Wrapping Up
This project ended up being less about memorizing AWS console clicks and more about understanding the full path a request takes from a browser, across the internet, into a server, into a database, and back again and where each layer of security and automation fits into that path. It’s the kind of thing that’s easy to use every day without ever really seeing.









