[{"data":1,"prerenderedAt":4808},["ShallowReactive",2],{"post-how-the-web-works":3},{"id":4,"title":5,"author":6,"body":7,"category":4788,"cover":4789,"date":4790,"description":4791,"extension":4792,"featured":65,"meta":4793,"navigation":65,"path":4794,"published":65,"readingTime":4795,"seo":4796,"sitemap":4797,"stem":4798,"tags":4799,"updated":4790,"__hash__":4807},"posts/posts/how-the-web-works.md","How the Web Works: From Browser to Server (Simple Explanation)","Kashyap Kumar",{"type":8,"value":9,"toc":4726},"minimark",[10,15,24,27,30,33,36,40,43,151,154,156,160,163,183,297,306,324,326,330,340,345,348,352,355,510,513,531,546,552,562,566,569,691,695,698,776,782,806,813,817,824,844,851,853,857,867,871,874,940,946,952,956,963,1019,1022,1026,1029,1032,1034,1038,1045,1053,1057,1060,1199,1203,1209,1212,1251,1254,1258,1307,1310,1312,1316,1322,1326,1329,1381,1384,1393,1415,1425,1431,1437,1451,1457,1467,1471,1474,1610,1624,1628,1634,1672,1675,1679,1739,1742,1744,1748,1754,1758,1765,1886,1892,1898,1902,1905,2004,2011,2015,2018,2021,2369,2372,2376,2379,2521,2524,2539,2546,2548,2552,2555,2559,2638,2642,2645,2771,2774,2788,2792,2810,2815,2858,2872,2878,2886,2906,2920,2922,2926,2933,2937,3106,3110,3117,3233,3236,3291,3295,3302,3375,3378,3418,3433,3437,3451,3545,3562,3566,3573,3591,3595,3602,3605,3619,3622,3626,3633,3644,3647,3659,3662,3684,3695,3697,3701,3704,3708,3711,3796,3799,3825,3828,3832,3835,3847,3859,3862,3864,3868,3871,3875,3970,3974,3977,3987,4005,4011,4019,4023,4026,4091,4098,4100,4104,4107,4356,4359,4361,4365,4368,4451,4454,4456,4460,4463,4538,4545,4570,4573,4575,4579,4582,4644,4647,4649,4653,4656,4716,4719,4722],[11,12,14],"h2",{"id":13},"what-actually-happens-when-you-visit-a-website","What Actually Happens When You Visit a Website?",[16,17,18,19,23],"p",{},"You open a browser, type ",[20,21,22],"code",{},"https://example.com",", press Enter, and a webpage appears in less than a second. It feels like magic.",[16,25,26],{},"It is not magic. It is a beautifully orchestrated sequence of steps involving your operating system, dozens of servers around the world, and your browser working together in perfect coordination. Every single time.",[16,28,29],{},"This post is a complete, honest explanation of that sequence. Whether you are brand new to tech or a seasoned backend developer, you will find value here. Beginners will get clear analogies and simple explanations. Experienced developers will find the full technical depth: packet-level details, TLS negotiation, HTTP header semantics, browser rendering pipelines, and more.",[16,31,32],{},"Let us walk through the entire journey, step by step.",[34,35],"hr",{},[11,37,39],{"id":38},"the-big-picture","The Big Picture",[16,41,42],{},"Before we zoom in on each step, here is the full end-to-end flow at a glance:",[44,45,50],"pre",{"className":46,"code":47,"language":48,"meta":49,"style":49},"language-txt shiki shiki-themes github-light","You type: https://example.com\n\n  [1] Browser checks its own DNS cache\n  [2] OS checks its local DNS cache + /etc/hosts\n  [3] Recursive DNS resolver queries the DNS hierarchy\n        Root Server --> .com TLD Server --> Authoritative NS\n  [4] DNS returns an IP address (e.g. 93.184.216.34)\n  [5] Browser opens a TCP connection (3-way handshake)\n  [6] TLS handshake (for HTTPS): establishes encrypted channel\n  [7] Browser sends an HTTP GET request\n  [8] Server receives request, runs application logic\n  [9] Server queries database (if needed)\n [10] Server builds and sends HTTP response (HTML, JSON, etc.)\n [11] Browser parses HTML, fetches sub-resources (CSS, JS, images)\n [12] Browser builds DOM + CSSOM --> Render Tree --> Layout --> Paint\n [13] Webpage appears on screen\n","txt","",[20,51,52,60,67,73,79,85,91,97,103,109,115,121,127,133,139,145],{"__ignoreMap":49},[53,54,57],"span",{"class":55,"line":56},"line",1,[53,58,59],{},"You type: https://example.com\n",[53,61,63],{"class":55,"line":62},2,[53,64,66],{"emptyLinePlaceholder":65},true,"\n",[53,68,70],{"class":55,"line":69},3,[53,71,72],{},"  [1] Browser checks its own DNS cache\n",[53,74,76],{"class":55,"line":75},4,[53,77,78],{},"  [2] OS checks its local DNS cache + /etc/hosts\n",[53,80,82],{"class":55,"line":81},5,[53,83,84],{},"  [3] Recursive DNS resolver queries the DNS hierarchy\n",[53,86,88],{"class":55,"line":87},6,[53,89,90],{},"        Root Server --> .com TLD Server --> Authoritative NS\n",[53,92,94],{"class":55,"line":93},7,[53,95,96],{},"  [4] DNS returns an IP address (e.g. 93.184.216.34)\n",[53,98,100],{"class":55,"line":99},8,[53,101,102],{},"  [5] Browser opens a TCP connection (3-way handshake)\n",[53,104,106],{"class":55,"line":105},9,[53,107,108],{},"  [6] TLS handshake (for HTTPS): establishes encrypted channel\n",[53,110,112],{"class":55,"line":111},10,[53,113,114],{},"  [7] Browser sends an HTTP GET request\n",[53,116,118],{"class":55,"line":117},11,[53,119,120],{},"  [8] Server receives request, runs application logic\n",[53,122,124],{"class":55,"line":123},12,[53,125,126],{},"  [9] Server queries database (if needed)\n",[53,128,130],{"class":55,"line":129},13,[53,131,132],{}," [10] Server builds and sends HTTP response (HTML, JSON, etc.)\n",[53,134,136],{"class":55,"line":135},14,[53,137,138],{}," [11] Browser parses HTML, fetches sub-resources (CSS, JS, images)\n",[53,140,142],{"class":55,"line":141},15,[53,143,144],{}," [12] Browser builds DOM + CSSOM --> Render Tree --> Layout --> Paint\n",[53,146,148],{"class":55,"line":147},16,[53,149,150],{}," [13] Webpage appears on screen\n",[16,152,153],{},"Each of these steps has significant depth. Let us explore them one by one.",[34,155],{},[11,157,159],{"id":158},"step-1-anatomy-of-a-url","Step 1: Anatomy of a URL",[16,161,162],{},"Before the browser can do anything, it needs to understand what you typed. A URL (Uniform Resource Locator) is not just an address, it is a structured specification that contains multiple distinct pieces of information.",[44,164,166],{"className":46,"code":165,"language":48,"meta":49,"style":49},"https://www.example.com:443/blog/article?id=42&lang=en#comments\n  |        |       |     |       |              |          |\nscheme   subdomain domain port   path         query     fragment\n",[20,167,168,173,178],{"__ignoreMap":49},[53,169,170],{"class":55,"line":56},[53,171,172],{},"https://www.example.com:443/blog/article?id=42&lang=en#comments\n",[53,174,175],{"class":55,"line":62},[53,176,177],{},"  |        |       |     |       |              |          |\n",[53,179,180],{"class":55,"line":69},[53,181,182],{},"scheme   subdomain domain port   path         query     fragment\n",[184,185,186,202],"table",{},[187,188,189],"thead",{},[190,191,192,196,199],"tr",{},[193,194,195],"th",{},"Part",[193,197,198],{},"Example",[193,200,201],{},"What it means",[203,204,205,219,232,245,258,271,284],"tbody",{},[190,206,207,211,216],{},[208,209,210],"td",{},"Scheme",[208,212,213],{},[20,214,215],{},"https",[208,217,218],{},"Which protocol to use (HTTP or HTTPS)",[190,220,221,224,229],{},[208,222,223],{},"Subdomain",[208,225,226],{},[20,227,228],{},"www",[208,230,231],{},"Subdivision of the domain",[190,233,234,237,242],{},[208,235,236],{},"Domain",[208,238,239],{},[20,240,241],{},"example.com",[208,243,244],{},"The human-readable name of the server",[190,246,247,250,255],{},[208,248,249],{},"Port",[208,251,252],{},[20,253,254],{},"443",[208,256,257],{},"Which \"door\" on the server to knock on (443 is default for HTTPS)",[190,259,260,263,268],{},[208,261,262],{},"Path",[208,264,265],{},[20,266,267],{},"/blog/article",[208,269,270],{},"Which resource on the server to request",[190,272,273,276,281],{},[208,274,275],{},"Query string",[208,277,278],{},[20,279,280],{},"?id=42&lang=en",[208,282,283],{},"Key-value pairs of extra data sent to the server",[190,285,286,289,294],{},[208,287,288],{},"Fragment",[208,290,291],{},[20,292,293],{},"#comments",[208,295,296],{},"Scrolls to a section on the page (never sent to the server)",[298,299,300],"blockquote",{},[16,301,302,303,305],{},"The fragment (",[20,304,293],{},") is handled entirely by the browser. It is stripped out before the request leaves your machine. The server never sees it.",[16,307,308,309,312,313,315,316,319,320,323],{},"The browser now knows: use HTTPS, contact ",[20,310,311],{},"www.example.com",", ask for ",[20,314,267],{},", and pass ",[20,317,318],{},"id=42"," and ",[20,321,322],{},"lang=en"," as parameters. But it does not have an IP address yet. That is where DNS comes in.",[34,325],{},[11,327,329],{"id":328},"step-2-dns-the-internets-phone-book","Step 2: DNS (The Internet's Phone Book)",[16,331,332,333,336,337,339],{},"Every device on the internet has a numeric IP address (like ",[20,334,335],{},"93.184.216.34","). Humans are bad at remembering numbers, so we invented domain names like ",[20,338,241],{},". DNS (Domain Name System) is the global distributed system that translates one into the other.",[341,342,344],"h3",{"id":343},"why-not-just-use-ip-addresses","Why Not Just Use IP Addresses?",[16,346,347],{},"Imagine if every phone contact was stored as a 12-digit number instead of a name. You would never memorize them. And if a company moved to a new building (changed servers), they would have to tell everyone their new phone number. DNS lets you update the mapping in one place and everyone finds the new server automatically.",[341,349,351],{"id":350},"the-dns-resolution-process","The DNS Resolution Process",[16,353,354],{},"DNS resolution is not a single lookup. It is a recursive journey through a hierarchy of specialized servers.",[44,356,358],{"className":46,"code":357,"language":48,"meta":49,"style":49},"                          Your Browser\n                               |\n                    (1) Check browser DNS cache\n                               |\n                    (2) Check OS cache + /etc/hosts\n                               |\n                    (3) Ask Recursive Resolver\n                         (usually your ISP\n                          or 8.8.8.8 / 1.1.1.1)\n                               |\n             +-----------------+-----------------+\n             |                                   |\n    (4) Ask Root Server             (7) Root says: ask .com TLD\n          (13 clusters             servers for \"example.com\"\n          worldwide)                             |\n                                    (8) Ask .com TLD Server\n                                                 |\n                                    (9) TLD says: ask\n                                    ns1.example.com (authoritative)\n                                                 |\n                                   (10) Ask Authoritative NS\n                                                 |\n                                   (11) Returns IP: 93.184.216.34\n                                                 |\n                    (12) Recursive Resolver returns IP to browser\n                               |\n                    (13) Browser caches IP with TTL\n                               |\n                    (14) Browser connects to 93.184.216.34\n",[20,359,360,365,370,375,379,384,388,393,398,403,407,412,417,422,427,432,437,443,449,455,460,466,471,477,482,488,493,499,504],{"__ignoreMap":49},[53,361,362],{"class":55,"line":56},[53,363,364],{},"                          Your Browser\n",[53,366,367],{"class":55,"line":62},[53,368,369],{},"                               |\n",[53,371,372],{"class":55,"line":69},[53,373,374],{},"                    (1) Check browser DNS cache\n",[53,376,377],{"class":55,"line":75},[53,378,369],{},[53,380,381],{"class":55,"line":81},[53,382,383],{},"                    (2) Check OS cache + /etc/hosts\n",[53,385,386],{"class":55,"line":87},[53,387,369],{},[53,389,390],{"class":55,"line":93},[53,391,392],{},"                    (3) Ask Recursive Resolver\n",[53,394,395],{"class":55,"line":99},[53,396,397],{},"                         (usually your ISP\n",[53,399,400],{"class":55,"line":105},[53,401,402],{},"                          or 8.8.8.8 / 1.1.1.1)\n",[53,404,405],{"class":55,"line":111},[53,406,369],{},[53,408,409],{"class":55,"line":117},[53,410,411],{},"             +-----------------+-----------------+\n",[53,413,414],{"class":55,"line":123},[53,415,416],{},"             |                                   |\n",[53,418,419],{"class":55,"line":129},[53,420,421],{},"    (4) Ask Root Server             (7) Root says: ask .com TLD\n",[53,423,424],{"class":55,"line":135},[53,425,426],{},"          (13 clusters             servers for \"example.com\"\n",[53,428,429],{"class":55,"line":141},[53,430,431],{},"          worldwide)                             |\n",[53,433,434],{"class":55,"line":147},[53,435,436],{},"                                    (8) Ask .com TLD Server\n",[53,438,440],{"class":55,"line":439},17,[53,441,442],{},"                                                 |\n",[53,444,446],{"class":55,"line":445},18,[53,447,448],{},"                                    (9) TLD says: ask\n",[53,450,452],{"class":55,"line":451},19,[53,453,454],{},"                                    ns1.example.com (authoritative)\n",[53,456,458],{"class":55,"line":457},20,[53,459,442],{},[53,461,463],{"class":55,"line":462},21,[53,464,465],{},"                                   (10) Ask Authoritative NS\n",[53,467,469],{"class":55,"line":468},22,[53,470,442],{},[53,472,474],{"class":55,"line":473},23,[53,475,476],{},"                                   (11) Returns IP: 93.184.216.34\n",[53,478,480],{"class":55,"line":479},24,[53,481,442],{},[53,483,485],{"class":55,"line":484},25,[53,486,487],{},"                    (12) Recursive Resolver returns IP to browser\n",[53,489,491],{"class":55,"line":490},26,[53,492,369],{},[53,494,496],{"class":55,"line":495},27,[53,497,498],{},"                    (13) Browser caches IP with TTL\n",[53,500,502],{"class":55,"line":501},28,[53,503,369],{},[53,505,507],{"class":55,"line":506},29,[53,508,509],{},"                    (14) Browser connects to 93.184.216.34\n",[16,511,512],{},"Let us break down the players:",[16,514,515,519,520,523,524,523,527,530],{},[516,517,518],"strong",{},"Root Name Servers:"," There are 13 logical root name servers (operated by groups like ICANN, NASA, and Verisign). They do not know IP addresses of individual domains, but they know which servers are responsible for each TLD (Top Level Domain) like ",[20,521,522],{},".com",", ",[20,525,526],{},".org",[20,528,529],{},".io",".",[16,532,533,536,537,539,540,542,543,530],{},[516,534,535],{},"TLD Name Servers:"," These know which authoritative name server is responsible for each domain under their TLD. The ",[20,538,522],{}," TLD server knows that ",[20,541,241],{}," is managed by ",[20,544,545],{},"ns1.example.com",[16,547,548,551],{},[516,549,550],{},"Authoritative Name Servers:"," These are the final authority. They hold the actual DNS records for a domain. When you register a domain and set up hosting, you configure these records (called \"A records\", \"CNAME records\", etc.).",[16,553,554,557,558,561],{},[516,555,556],{},"Recursive Resolver:"," This is the engine that does the hard work. It is a server (usually run by your ISP, or a public resolver like Google's ",[20,559,560],{},"8.8.8.8",") that takes your query, walks the hierarchy, collects the answer, and returns it to you. It also caches the result for efficiency.",[341,563,565],{"id":564},"dns-record-types","DNS Record Types",[16,567,568],{},"DNS is not just about IP addresses. It stores several types of records:",[184,570,571,583],{},[187,572,573],{},[190,574,575,578,581],{},[193,576,577],{},"Record Type",[193,579,580],{},"Purpose",[193,582,198],{},[203,584,585,600,615,630,645,660,675],{},[190,586,587,592,595],{},[208,588,589],{},[20,590,591],{},"A",[208,593,594],{},"Maps domain to IPv4 address",[208,596,597],{},[20,598,599],{},"example.com --> 93.184.216.34",[190,601,602,607,610],{},[208,603,604],{},[20,605,606],{},"AAAA",[208,608,609],{},"Maps domain to IPv6 address",[208,611,612],{},[20,613,614],{},"example.com --> 2606:2800:220:1:248:1893:25c8:1946",[190,616,617,622,625],{},[208,618,619],{},[20,620,621],{},"CNAME",[208,623,624],{},"Alias from one domain to another",[208,626,627],{},[20,628,629],{},"www.example.com --> example.com",[190,631,632,637,640],{},[208,633,634],{},[20,635,636],{},"MX",[208,638,639],{},"Mail server for the domain",[208,641,642],{},[20,643,644],{},"example.com --> mail.example.com",[190,646,647,652,655],{},[208,648,649],{},[20,650,651],{},"TXT",[208,653,654],{},"Arbitrary text (used for SPF, DKIM, domain verification)",[208,656,657],{},[20,658,659],{},"\"v=spf1 include:...\"",[190,661,662,667,670],{},[208,663,664],{},[20,665,666],{},"NS",[208,668,669],{},"Which servers are authoritative for this domain",[208,671,672],{},[20,673,674],{},"example.com --> ns1.example.com",[190,676,677,682,685],{},[208,678,679],{},[20,680,681],{},"TTL",[208,683,684],{},"Time To Live, how long resolvers should cache this record",[208,686,687,690],{},[20,688,689],{},"3600"," (1 hour)",[341,692,694],{"id":693},"dns-lookup-in-practice","DNS Lookup in Practice",[16,696,697],{},"You can run a DNS lookup yourself right now. Open your terminal:",[44,699,703],{"className":700,"code":701,"language":702,"meta":49,"style":49},"language-bash shiki shiki-themes github-light","# Simple lookup\ndig example.com\n\n# Look for a specific record type\ndig example.com MX\n\n# Trace the entire resolution path\ndig +trace example.com\n\n# Use a specific DNS server\ndig @8.8.8.8 example.com\n","bash",[20,704,705,711,721,725,730,740,744,749,758,762,767],{"__ignoreMap":49},[53,706,707],{"class":55,"line":56},[53,708,710],{"class":709},"sAwPA","# Simple lookup\n",[53,712,713,717],{"class":55,"line":62},[53,714,716],{"class":715},"s7eDp","dig",[53,718,720],{"class":719},"sYBdl"," example.com\n",[53,722,723],{"class":55,"line":69},[53,724,66],{"emptyLinePlaceholder":65},[53,726,727],{"class":55,"line":75},[53,728,729],{"class":709},"# Look for a specific record type\n",[53,731,732,734,737],{"class":55,"line":81},[53,733,716],{"class":715},[53,735,736],{"class":719}," example.com",[53,738,739],{"class":719}," MX\n",[53,741,742],{"class":55,"line":87},[53,743,66],{"emptyLinePlaceholder":65},[53,745,746],{"class":55,"line":93},[53,747,748],{"class":709},"# Trace the entire resolution path\n",[53,750,751,753,756],{"class":55,"line":99},[53,752,716],{"class":715},[53,754,755],{"class":719}," +trace",[53,757,720],{"class":719},[53,759,760],{"class":55,"line":105},[53,761,66],{"emptyLinePlaceholder":65},[53,763,764],{"class":55,"line":111},[53,765,766],{"class":709},"# Use a specific DNS server\n",[53,768,769,771,774],{"class":55,"line":117},[53,770,716],{"class":715},[53,772,773],{"class":719}," @8.8.8.8",[53,775,720],{"class":719},[16,777,778,779,781],{},"A typical ",[20,780,716],{}," response looks like this:",[44,783,785],{"className":46,"code":784,"language":48,"meta":49,"style":49},";; ANSWER SECTION:\nexample.com.    86400   IN  A   93.184.216.34\n\n; name         TTL   class type  value\n",[20,786,787,792,797,801],{"__ignoreMap":49},[53,788,789],{"class":55,"line":56},[53,790,791],{},";; ANSWER SECTION:\n",[53,793,794],{"class":55,"line":62},[53,795,796],{},"example.com.    86400   IN  A   93.184.216.34\n",[53,798,799],{"class":55,"line":69},[53,800,66],{"emptyLinePlaceholder":65},[53,802,803],{"class":55,"line":75},[53,804,805],{},"; name         TTL   class type  value\n",[16,807,808,809,812],{},"The TTL here is ",[20,810,811],{},"86400"," seconds (24 hours). This means resolvers can cache this record for 24 hours before asking again. Lowering the TTL is important before moving a site to a new server, so DNS changes propagate quickly.",[341,814,816],{"id":815},"etchosts-the-override-file","/etc/hosts: The Override File",[16,818,819,820,823],{},"Before your OS even contacts a DNS server, it checks a local file called ",[20,821,822],{},"/etc/hosts",". You can put entries there to override DNS:",[44,825,827],{"className":46,"code":826,"language":48,"meta":49,"style":49},"# /etc/hosts\n127.0.0.1   localhost\n192.168.1.10  my-dev-server.local\n",[20,828,829,834,839],{"__ignoreMap":49},[53,830,831],{"class":55,"line":56},[53,832,833],{},"# /etc/hosts\n",[53,835,836],{"class":55,"line":62},[53,837,838],{},"127.0.0.1   localhost\n",[53,840,841],{"class":55,"line":69},[53,842,843],{},"192.168.1.10  my-dev-server.local\n",[16,845,846,847,850],{},"This is why developers often add entries like ",[20,848,849],{},"127.0.0.1 myapp.test"," to test local sites with real domain names. It bypasses DNS entirely.",[34,852],{},[11,854,856],{"id":855},"step-3-tcpip-how-packets-travel-across-the-world","Step 3: TCP/IP (How Packets Travel Across the World)",[16,858,859,860,862,863,866],{},"Now the browser has an IP address: ",[20,861,335],{},". But the internet does not send whole files at once. It breaks everything into small chunks called ",[516,864,865],{},"packets",", sends them independently across the network, and reassembles them at the destination. This is the job of the TCP/IP suite.",[341,868,870],{"id":869},"the-internet-protocol-stack","The Internet Protocol Stack",[16,872,873],{},"The internet is built on a layered model. Each layer handles a specific job and hands work to the layer below it:",[44,875,877],{"className":46,"code":876,"language":48,"meta":49,"style":49},"+-----------------------------+\n|   Application Layer         |  HTTP, HTTPS, DNS, SMTP\n|   (What data means)         |\n+-----------------------------+\n|   Transport Layer           |  TCP, UDP\n|   (Reliable delivery)       |\n+-----------------------------+\n|   Internet Layer            |  IP (IPv4, IPv6)\n|   (Routing packets)         |\n+-----------------------------+\n|   Network Access Layer      |  Ethernet, Wi-Fi\n|   (Physical transmission)   |\n+-----------------------------+\n",[20,878,879,884,889,894,898,903,908,912,917,922,926,931,936],{"__ignoreMap":49},[53,880,881],{"class":55,"line":56},[53,882,883],{},"+-----------------------------+\n",[53,885,886],{"class":55,"line":62},[53,887,888],{},"|   Application Layer         |  HTTP, HTTPS, DNS, SMTP\n",[53,890,891],{"class":55,"line":69},[53,892,893],{},"|   (What data means)         |\n",[53,895,896],{"class":55,"line":75},[53,897,883],{},[53,899,900],{"class":55,"line":81},[53,901,902],{},"|   Transport Layer           |  TCP, UDP\n",[53,904,905],{"class":55,"line":87},[53,906,907],{},"|   (Reliable delivery)       |\n",[53,909,910],{"class":55,"line":93},[53,911,883],{},[53,913,914],{"class":55,"line":99},[53,915,916],{},"|   Internet Layer            |  IP (IPv4, IPv6)\n",[53,918,919],{"class":55,"line":105},[53,920,921],{},"|   (Routing packets)         |\n",[53,923,924],{"class":55,"line":111},[53,925,883],{},[53,927,928],{"class":55,"line":117},[53,929,930],{},"|   Network Access Layer      |  Ethernet, Wi-Fi\n",[53,932,933],{"class":55,"line":123},[53,934,935],{},"|   (Physical transmission)   |\n",[53,937,938],{"class":55,"line":129},[53,939,883],{},[16,941,942,945],{},[516,943,944],{},"IP (Internet Protocol)"," handles addressing and routing. It labels each packet with a source IP address and a destination IP address, and routers around the world forward packets toward the destination based on routing tables.",[16,947,948,951],{},[516,949,950],{},"TCP (Transmission Control Protocol)"," adds reliability on top of IP. It guarantees that packets arrive, that they arrive in order, and that lost packets are retransmitted. This is critical for loading web pages correctly.",[341,953,955],{"id":954},"the-tcp-3-way-handshake","The TCP 3-Way Handshake",[16,957,958,959,962],{},"Before any data is sent, TCP establishes a ",[516,960,961],{},"connection"," between the browser and the server. This takes exactly 3 steps:",[44,964,966],{"className":46,"code":965,"language":48,"meta":49,"style":49},"Browser (Client)                      Server\n      |                                  |\n      |-------- SYN (seq=x) ----------->|   \"Hello, I want to connect\"\n      |                                  |\n      |\u003C------- SYN-ACK (seq=y,ack=x+1)-|   \"Hello! I acknowledge, ready?\"\n      |                                  |\n      |-------- ACK (ack=y+1) ---------->|   \"Great, let us talk\"\n      |                                  |\n      |    (connection established)      |\n      |                                  |\n      |====== Data can now flow =========|\n",[20,967,968,973,978,983,987,992,996,1001,1005,1010,1014],{"__ignoreMap":49},[53,969,970],{"class":55,"line":56},[53,971,972],{},"Browser (Client)                      Server\n",[53,974,975],{"class":55,"line":62},[53,976,977],{},"      |                                  |\n",[53,979,980],{"class":55,"line":69},[53,981,982],{},"      |-------- SYN (seq=x) ----------->|   \"Hello, I want to connect\"\n",[53,984,985],{"class":55,"line":75},[53,986,977],{},[53,988,989],{"class":55,"line":81},[53,990,991],{},"      |\u003C------- SYN-ACK (seq=y,ack=x+1)-|   \"Hello! I acknowledge, ready?\"\n",[53,993,994],{"class":55,"line":87},[53,995,977],{},[53,997,998],{"class":55,"line":93},[53,999,1000],{},"      |-------- ACK (ack=y+1) ---------->|   \"Great, let us talk\"\n",[53,1002,1003],{"class":55,"line":99},[53,1004,977],{},[53,1006,1007],{"class":55,"line":105},[53,1008,1009],{},"      |    (connection established)      |\n",[53,1011,1012],{"class":55,"line":111},[53,1013,977],{},[53,1015,1016],{"class":55,"line":117},[53,1017,1018],{},"      |====== Data can now flow =========|\n",[16,1020,1021],{},"SYN means \"synchronize\". Each side sends its initial sequence number, and the other side acknowledges it. After this handshake, both sides are synchronized and data can flow. This roundtrip takes time, roughly one RTT (Round Trip Time), which might be 10ms on a local network or 150ms to a server on the other side of the world.",[341,1023,1025],{"id":1024},"why-not-just-use-udp","Why Not Just Use UDP?",[16,1027,1028],{},"UDP (User Datagram Protocol) is a simpler transport protocol. It sends packets without handshakes, without ordering guarantees, and without retransmission. It is faster but unreliable.",[16,1030,1031],{},"UDP is used when speed matters more than accuracy: video calls, live game updates, DNS queries. For web pages, you need every byte to arrive correctly, so TCP is the right choice (though HTTP/3 switches to QUIC, which is UDP-based but adds its own reliability layer).",[34,1033],{},[11,1035,1037],{"id":1036},"step-4-tls-the-encrypted-tunnel-for-https","Step 4: TLS, the Encrypted Tunnel (for HTTPS)",[16,1039,1040,1041,1044],{},"If the URL starts with ",[20,1042,1043],{},"https://",", the browser must now establish a secure, encrypted connection using TLS (Transport Layer Security). TLS runs on top of TCP and ensures that no one eavesdropping on the network can read or tamper with your data.",[298,1046,1047],{},[16,1048,1049,1052],{},[516,1050,1051],{},"HTTP vs HTTPS:"," HTTP sends everything as plain text. Any router or ISP between you and the server can read it. HTTPS encrypts the entire conversation. Always use HTTPS.",[341,1054,1056],{"id":1055},"the-tls-handshake","The TLS Handshake",[16,1058,1059],{},"The TLS handshake is more complex than TCP's, but the goal is clear: agree on encryption settings and verify the server's identity, all without ever sending a secret key over the wire.",[44,1061,1063],{"className":46,"code":1062,"language":48,"meta":49,"style":49},"Browser (Client)                            Server\n      |                                        |\n      |-- ClientHello ------------------------>|\n      |   (TLS version, cipher suites,         |\n      |    random number A)                    |\n      |                                        |\n      |\u003C-- ServerHello ----------------------- |\n      |    (chosen cipher suite,               |\n      |     random number B,                   |\n      |     server's TLS certificate)          |\n      |                                        |\n      | [Browser validates certificate]        |\n      |  - Is it signed by a trusted CA?       |\n      |  - Does it match the domain?           |\n      |  - Is it expired?                      |\n      |                                        |\n      |-- Key Exchange ----------------------->|\n      |   (using server's public key to        |\n      |    encrypt a pre-master secret,        |\n      |    or via Diffie-Hellman key exchange) |\n      |                                        |\n      | [Both sides derive session keys        |\n      |  from random A + random B + secret]    |\n      |                                        |\n      |-- Finished (encrypted) -------------->|\n      |\u003C-- Finished (encrypted) --------------|\n      |                                        |\n      |===== All further data is encrypted ====|\n",[20,1064,1065,1070,1075,1080,1085,1090,1094,1099,1104,1109,1114,1118,1123,1128,1133,1138,1142,1147,1152,1157,1162,1166,1171,1176,1180,1185,1190,1194],{"__ignoreMap":49},[53,1066,1067],{"class":55,"line":56},[53,1068,1069],{},"Browser (Client)                            Server\n",[53,1071,1072],{"class":55,"line":62},[53,1073,1074],{},"      |                                        |\n",[53,1076,1077],{"class":55,"line":69},[53,1078,1079],{},"      |-- ClientHello ------------------------>|\n",[53,1081,1082],{"class":55,"line":75},[53,1083,1084],{},"      |   (TLS version, cipher suites,         |\n",[53,1086,1087],{"class":55,"line":81},[53,1088,1089],{},"      |    random number A)                    |\n",[53,1091,1092],{"class":55,"line":87},[53,1093,1074],{},[53,1095,1096],{"class":55,"line":93},[53,1097,1098],{},"      |\u003C-- ServerHello ----------------------- |\n",[53,1100,1101],{"class":55,"line":99},[53,1102,1103],{},"      |    (chosen cipher suite,               |\n",[53,1105,1106],{"class":55,"line":105},[53,1107,1108],{},"      |     random number B,                   |\n",[53,1110,1111],{"class":55,"line":111},[53,1112,1113],{},"      |     server's TLS certificate)          |\n",[53,1115,1116],{"class":55,"line":117},[53,1117,1074],{},[53,1119,1120],{"class":55,"line":123},[53,1121,1122],{},"      | [Browser validates certificate]        |\n",[53,1124,1125],{"class":55,"line":129},[53,1126,1127],{},"      |  - Is it signed by a trusted CA?       |\n",[53,1129,1130],{"class":55,"line":135},[53,1131,1132],{},"      |  - Does it match the domain?           |\n",[53,1134,1135],{"class":55,"line":141},[53,1136,1137],{},"      |  - Is it expired?                      |\n",[53,1139,1140],{"class":55,"line":147},[53,1141,1074],{},[53,1143,1144],{"class":55,"line":439},[53,1145,1146],{},"      |-- Key Exchange ----------------------->|\n",[53,1148,1149],{"class":55,"line":445},[53,1150,1151],{},"      |   (using server's public key to        |\n",[53,1153,1154],{"class":55,"line":451},[53,1155,1156],{},"      |    encrypt a pre-master secret,        |\n",[53,1158,1159],{"class":55,"line":457},[53,1160,1161],{},"      |    or via Diffie-Hellman key exchange) |\n",[53,1163,1164],{"class":55,"line":462},[53,1165,1074],{},[53,1167,1168],{"class":55,"line":468},[53,1169,1170],{},"      | [Both sides derive session keys        |\n",[53,1172,1173],{"class":55,"line":473},[53,1174,1175],{},"      |  from random A + random B + secret]    |\n",[53,1177,1178],{"class":55,"line":479},[53,1179,1074],{},[53,1181,1182],{"class":55,"line":484},[53,1183,1184],{},"      |-- Finished (encrypted) -------------->|\n",[53,1186,1187],{"class":55,"line":490},[53,1188,1189],{},"      |\u003C-- Finished (encrypted) --------------|\n",[53,1191,1192],{"class":55,"line":495},[53,1193,1074],{},[53,1195,1196],{"class":55,"line":501},[53,1197,1198],{},"      |===== All further data is encrypted ====|\n",[341,1200,1202],{"id":1201},"tls-certificates-proving-identity","TLS Certificates: Proving Identity",[16,1204,1205,1206,1208],{},"When a server presents a TLS certificate, it is saying: \"I am ",[20,1207,241],{},", and here is my signed proof.\" The proof is a digital signature from a Certificate Authority (CA), a trusted third party like Let's Encrypt, DigiCert, or Comodo.",[16,1210,1211],{},"Your browser comes pre-installed with a list of trusted root CAs. If the server's certificate is signed (directly or through a chain) by one of these CAs, the browser trusts it. If not, you see that scary red warning.",[44,1213,1215],{"className":46,"code":1214,"language":48,"meta":49,"style":49},"Certificate Chain:\n\n  Root CA (pre-trusted by browser)\n      |\n      +--> Intermediate CA (signed by Root)\n                |\n                +--> example.com certificate (signed by Intermediate)\n",[20,1216,1217,1222,1226,1231,1236,1241,1246],{"__ignoreMap":49},[53,1218,1219],{"class":55,"line":56},[53,1220,1221],{},"Certificate Chain:\n",[53,1223,1224],{"class":55,"line":62},[53,1225,66],{"emptyLinePlaceholder":65},[53,1227,1228],{"class":55,"line":69},[53,1229,1230],{},"  Root CA (pre-trusted by browser)\n",[53,1232,1233],{"class":55,"line":75},[53,1234,1235],{},"      |\n",[53,1237,1238],{"class":55,"line":81},[53,1239,1240],{},"      +--> Intermediate CA (signed by Root)\n",[53,1242,1243],{"class":55,"line":87},[53,1244,1245],{},"                |\n",[53,1247,1248],{"class":55,"line":93},[53,1249,1250],{},"                +--> example.com certificate (signed by Intermediate)\n",[16,1252,1253],{},"Browsers do not trust the end certificate directly. They walk the chain up to a root they already trust.",[341,1255,1257],{"id":1256},"what-tls-protects-against","What TLS Protects Against",[184,1259,1260,1272],{},[187,1261,1262],{},[190,1263,1264,1267,1269],{},[193,1265,1266],{},"Threat",[193,1268,201],{},[193,1270,1271],{},"How TLS helps",[203,1273,1274,1285,1296],{},[190,1275,1276,1279,1282],{},[208,1277,1278],{},"Eavesdropping",[208,1280,1281],{},"Someone reads your data in transit",[208,1283,1284],{},"Encryption makes data unreadable",[190,1286,1287,1290,1293],{},[208,1288,1289],{},"Tampering",[208,1291,1292],{},"Someone modifies data in transit",[208,1294,1295],{},"MAC (Message Auth Code) detects changes",[190,1297,1298,1301,1304],{},[208,1299,1300],{},"Impersonation",[208,1302,1303],{},"A fake server pretends to be your bank",[208,1305,1306],{},"Certificate verification proves identity",[16,1308,1309],{},"After the TLS handshake, the browser and server share a symmetric encryption key (fast, unlike asymmetric encryption). All HTTP traffic from this point is encrypted using that key.",[34,1311],{},[11,1313,1315],{"id":1314},"step-5-the-http-request","Step 5: The HTTP Request",[16,1317,1318,1319,530],{},"With a TCP connection established and TLS negotiated, the browser is finally ready to ask for the page. It sends an ",[516,1320,1321],{},"HTTP request",[341,1323,1325],{"id":1324},"http-request-structure","HTTP Request Structure",[16,1327,1328],{},"An HTTP request has three parts: a request line, headers, and an optional body.",[44,1330,1334],{"className":1331,"code":1332,"language":1333,"meta":49,"style":49},"language-http shiki shiki-themes github-light","GET /blog/article?id=42&lang=en HTTP/1.1\nHost: www.example.com\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\nAccept-Language: en-US,en;q=0.5\nAccept-Encoding: gzip, deflate, br\nConnection: keep-alive\nCookie: session_id=abc123; theme=dark\nCache-Control: max-age=0\n","http",[20,1335,1336,1341,1346,1351,1356,1361,1366,1371,1376],{"__ignoreMap":49},[53,1337,1338],{"class":55,"line":56},[53,1339,1340],{},"GET /blog/article?id=42&lang=en HTTP/1.1\n",[53,1342,1343],{"class":55,"line":62},[53,1344,1345],{},"Host: www.example.com\n",[53,1347,1348],{"class":55,"line":69},[53,1349,1350],{},"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...\n",[53,1352,1353],{"class":55,"line":75},[53,1354,1355],{},"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n",[53,1357,1358],{"class":55,"line":81},[53,1359,1360],{},"Accept-Language: en-US,en;q=0.5\n",[53,1362,1363],{"class":55,"line":87},[53,1364,1365],{},"Accept-Encoding: gzip, deflate, br\n",[53,1367,1368],{"class":55,"line":93},[53,1369,1370],{},"Connection: keep-alive\n",[53,1372,1373],{"class":55,"line":99},[53,1374,1375],{},"Cookie: session_id=abc123; theme=dark\n",[53,1377,1378],{"class":55,"line":105},[53,1379,1380],{},"Cache-Control: max-age=0\n",[16,1382,1383],{},"Let us break this down line by line:",[16,1385,1386,1389,1390],{},[516,1387,1388],{},"Request Line:"," ",[20,1391,1392],{},"GET /blog/article?id=42&lang=en HTTP/1.1",[1394,1395,1396,1403,1409],"ul",{},[1397,1398,1399,1402],"li",{},[20,1400,1401],{},"GET",": The HTTP method (see methods below)",[1397,1404,1405,1408],{},[20,1406,1407],{},"/blog/article?id=42&lang=en",": The path + query string",[1397,1410,1411,1414],{},[20,1412,1413],{},"HTTP/1.1",": The protocol version",[16,1416,1417,1420,1421,1424],{},[516,1418,1419],{},"Host Header:"," The domain name. This is crucial because one server can host hundreds of different websites on the same IP address. The ",[20,1422,1423],{},"Host"," header tells the server which website you want. This is called virtual hosting.",[16,1426,1427,1430],{},[516,1428,1429],{},"User-Agent:"," Identifies the browser and OS. Servers can use this to send different content to mobile vs desktop browsers (though responsive CSS is preferred).",[16,1432,1433,1436],{},[516,1434,1435],{},"Accept:"," Tells the server what types of content the browser understands, in order of preference.",[16,1438,1439,1442,1443,1446,1447,1450],{},[516,1440,1441],{},"Accept-Encoding:"," The browser advertises which compression algorithms it supports. Servers typically respond with ",[20,1444,1445],{},"gzip"," or ",[20,1448,1449],{},"br"," (Brotli) compressed content, which can reduce file size by 70-90%.",[16,1452,1453,1456],{},[516,1454,1455],{},"Cookie:"," Cookies are sent with every request to the domain. This is how the server recognizes returning users and maintains sessions.",[16,1458,1459,1462,1463,1466],{},[516,1460,1461],{},"Cache-Control:"," Hints about caching behavior. ",[20,1464,1465],{},"max-age=0"," tells the server the browser wants a fresh copy.",[341,1468,1470],{"id":1469},"http-methods","HTTP Methods",[16,1472,1473],{},"Different methods have different meanings and different semantics:",[184,1475,1476,1494],{},[187,1477,1478],{},[190,1479,1480,1483,1485,1488,1491],{},[193,1481,1482],{},"Method",[193,1484,580],{},[193,1486,1487],{},"Has Body?",[193,1489,1490],{},"Safe?",[193,1492,1493],{},"Idempotent?",[203,1495,1496,1513,1529,1545,1561,1578,1594],{},[190,1497,1498,1502,1505,1508,1511],{},[208,1499,1500],{},[20,1501,1401],{},[208,1503,1504],{},"Retrieve a resource",[208,1506,1507],{},"No",[208,1509,1510],{},"Yes",[208,1512,1510],{},[190,1514,1515,1520,1523,1525,1527],{},[208,1516,1517],{},[20,1518,1519],{},"POST",[208,1521,1522],{},"Create a new resource",[208,1524,1510],{},[208,1526,1507],{},[208,1528,1507],{},[190,1530,1531,1536,1539,1541,1543],{},[208,1532,1533],{},[20,1534,1535],{},"PUT",[208,1537,1538],{},"Replace a resource entirely",[208,1540,1510],{},[208,1542,1507],{},[208,1544,1510],{},[190,1546,1547,1552,1555,1557,1559],{},[208,1548,1549],{},[20,1550,1551],{},"PATCH",[208,1553,1554],{},"Partially update a resource",[208,1556,1510],{},[208,1558,1507],{},[208,1560,1507],{},[190,1562,1563,1568,1571,1574,1576],{},[208,1564,1565],{},[20,1566,1567],{},"DELETE",[208,1569,1570],{},"Delete a resource",[208,1572,1573],{},"Sometimes",[208,1575,1507],{},[208,1577,1510],{},[190,1579,1580,1585,1588,1590,1592],{},[208,1581,1582],{},[20,1583,1584],{},"HEAD",[208,1586,1587],{},"Like GET but no response body",[208,1589,1507],{},[208,1591,1510],{},[208,1593,1510],{},[190,1595,1596,1601,1604,1606,1608],{},[208,1597,1598],{},[20,1599,1600],{},"OPTIONS",[208,1602,1603],{},"Ask what methods are allowed",[208,1605,1507],{},[208,1607,1510],{},[208,1609,1510],{},[16,1611,1612,1615,1616,1619,1620,1623],{},[516,1613,1614],{},"Safe"," means the method does not change server state (only reads data).\n",[516,1617,1618],{},"Idempotent"," means calling the same method multiple times has the same result as calling it once. ",[20,1621,1622],{},"DELETE /users/42"," twice should not error the second time (the user is already gone).",[341,1625,1627],{"id":1626},"a-post-request-with-a-body","A POST Request with a Body",[16,1629,1630,1631,1633],{},"When you submit a login form, the browser sends a ",[20,1632,1519],{}," request with a body:",[44,1635,1637],{"className":1331,"code":1636,"language":1333,"meta":49,"style":49},"POST /api/login HTTP/1.1\nHost: www.example.com\nContent-Type: application/json\nContent-Length: 47\nAccept: application/json\n\n{\"email\": \"user@example.com\", \"password\": \"...\"}\n",[20,1638,1639,1644,1648,1653,1658,1663,1667],{"__ignoreMap":49},[53,1640,1641],{"class":55,"line":56},[53,1642,1643],{},"POST /api/login HTTP/1.1\n",[53,1645,1646],{"class":55,"line":62},[53,1647,1345],{},[53,1649,1650],{"class":55,"line":69},[53,1651,1652],{},"Content-Type: application/json\n",[53,1654,1655],{"class":55,"line":75},[53,1656,1657],{},"Content-Length: 47\n",[53,1659,1660],{"class":55,"line":81},[53,1661,1662],{},"Accept: application/json\n",[53,1664,1665],{"class":55,"line":87},[53,1666,66],{"emptyLinePlaceholder":65},[53,1668,1669],{"class":55,"line":93},[53,1670,1671],{},"{\"email\": \"user@example.com\", \"password\": \"...\"}\n",[16,1673,1674],{},"The blank line between headers and body is mandatory in HTTP. It tells the parser \"headers are done, body starts here.\"",[341,1676,1678],{"id":1677},"http11-vs-http2-vs-http3","HTTP/1.1 vs HTTP/2 vs HTTP/3",[184,1680,1681,1694],{},[187,1682,1683],{},[190,1684,1685,1688,1691],{},[193,1686,1687],{},"Version",[193,1689,1690],{},"Year",[193,1692,1693],{},"Key Feature",[203,1695,1696,1707,1717,1728],{},[190,1697,1698,1701,1704],{},[208,1699,1700],{},"HTTP/1.0",[208,1702,1703],{},"1996",[208,1705,1706],{},"One request per connection",[190,1708,1709,1711,1714],{},[208,1710,1413],{},[208,1712,1713],{},"1997",[208,1715,1716],{},"Keep-alive (reuse connection), pipelining",[190,1718,1719,1722,1725],{},[208,1720,1721],{},"HTTP/2",[208,1723,1724],{},"2015",[208,1726,1727],{},"Multiplexing (multiple requests on one connection), header compression, server push",[190,1729,1730,1733,1736],{},[208,1731,1732],{},"HTTP/3",[208,1734,1735],{},"2022",[208,1737,1738],{},"Built on QUIC/UDP, 0-RTT connection setup, no head-of-line blocking",[16,1740,1741],{},"HTTP/2 multiplexing is a big deal. With HTTP/1.1, if you have 30 CSS files, images, and scripts to load, browsers open 6 parallel TCP connections per domain and pipeline requests. HTTP/2 handles all 30 over a single connection with no waiting.",[34,1743],{},[11,1745,1747],{"id":1746},"step-6-the-server-receives-the-request","Step 6: The Server Receives the Request",[16,1749,1750,1751,1753],{},"The request has traveled across the internet, through routers, across fiber optic cables or wireless networks, and has arrived at a server running at IP address ",[20,1752,335],{},". What happens on the server side?",[341,1755,1757],{"id":1756},"the-web-server","The Web Server",[16,1759,1760,1761,1764],{},"The first program that receives your request is a ",[516,1762,1763],{},"web server",": software like Nginx, Apache, or Caddy. Think of the web server as a receptionist in a large office building. It handles the initial connection, reads the request, and decides who should handle it.",[44,1766,1768],{"className":46,"code":1767,"language":48,"meta":49,"style":49},"Incoming request\n      |\n      v\n+-----------+\n|   Nginx   |  (Web Server / Reverse Proxy)\n|           |\n|  - Handles TLS termination\n|  - Serves static files directly (HTML, CSS, images)\n|  - Proxies dynamic requests to app server\n+-----------+\n      |\n      | (if dynamic content needed)\n      v\n+------------------+\n|  App Server      |  (Node.js, PHP-FPM, Gunicorn, etc.)\n|                  |\n|  - Runs your code\n|  - Handles business logic\n|  - Queries database\n+------------------+\n      |\n      v\n+------------------+\n|  Database        |  (PostgreSQL, MySQL, Redis, etc.)\n+------------------+\n",[20,1769,1770,1775,1779,1784,1789,1794,1799,1804,1809,1814,1818,1822,1827,1831,1836,1841,1846,1851,1856,1861,1865,1869,1873,1877,1882],{"__ignoreMap":49},[53,1771,1772],{"class":55,"line":56},[53,1773,1774],{},"Incoming request\n",[53,1776,1777],{"class":55,"line":62},[53,1778,1235],{},[53,1780,1781],{"class":55,"line":69},[53,1782,1783],{},"      v\n",[53,1785,1786],{"class":55,"line":75},[53,1787,1788],{},"+-----------+\n",[53,1790,1791],{"class":55,"line":81},[53,1792,1793],{},"|   Nginx   |  (Web Server / Reverse Proxy)\n",[53,1795,1796],{"class":55,"line":87},[53,1797,1798],{},"|           |\n",[53,1800,1801],{"class":55,"line":93},[53,1802,1803],{},"|  - Handles TLS termination\n",[53,1805,1806],{"class":55,"line":99},[53,1807,1808],{},"|  - Serves static files directly (HTML, CSS, images)\n",[53,1810,1811],{"class":55,"line":105},[53,1812,1813],{},"|  - Proxies dynamic requests to app server\n",[53,1815,1816],{"class":55,"line":111},[53,1817,1788],{},[53,1819,1820],{"class":55,"line":117},[53,1821,1235],{},[53,1823,1824],{"class":55,"line":123},[53,1825,1826],{},"      | (if dynamic content needed)\n",[53,1828,1829],{"class":55,"line":129},[53,1830,1783],{},[53,1832,1833],{"class":55,"line":135},[53,1834,1835],{},"+------------------+\n",[53,1837,1838],{"class":55,"line":141},[53,1839,1840],{},"|  App Server      |  (Node.js, PHP-FPM, Gunicorn, etc.)\n",[53,1842,1843],{"class":55,"line":147},[53,1844,1845],{},"|                  |\n",[53,1847,1848],{"class":55,"line":439},[53,1849,1850],{},"|  - Runs your code\n",[53,1852,1853],{"class":55,"line":445},[53,1854,1855],{},"|  - Handles business logic\n",[53,1857,1858],{"class":55,"line":451},[53,1859,1860],{},"|  - Queries database\n",[53,1862,1863],{"class":55,"line":457},[53,1864,1835],{},[53,1866,1867],{"class":55,"line":462},[53,1868,1235],{},[53,1870,1871],{"class":55,"line":468},[53,1872,1783],{},[53,1874,1875],{"class":55,"line":473},[53,1876,1835],{},[53,1878,1879],{"class":55,"line":479},[53,1880,1881],{},"|  Database        |  (PostgreSQL, MySQL, Redis, etc.)\n",[53,1883,1884],{"class":55,"line":484},[53,1885,1835],{},[16,1887,1888,1891],{},[516,1889,1890],{},"Static files"," are files that are the same for every user: images, fonts, CSS files, downloaded PDFs. Nginx can serve these directly from disk without touching your application code. This is extremely fast.",[16,1893,1894,1897],{},[516,1895,1896],{},"Dynamic content"," is content that changes per user or per request: your inbox page, a product page with live inventory, an API response with your profile data. For these, Nginx forwards the request to the application server.",[341,1899,1901],{"id":1900},"nginx-configuration-simplified","Nginx Configuration (Simplified)",[16,1903,1904],{},"Here is what a simplified Nginx config for a web application looks like:",[44,1906,1910],{"className":1907,"code":1908,"language":1909,"meta":49,"style":49},"language-nginx shiki shiki-themes github-light","server {\n    listen 443 ssl;\n    server_name example.com;\n\n    # Serve static files directly\n    location /static/ {\n        root /var/www/myapp;\n        expires 1y;\n        add_header Cache-Control \"public, immutable\";\n    }\n\n    # Forward everything else to Node.js app\n    location / {\n        proxy_pass http://127.0.0.1:3000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    }\n}\n","nginx",[20,1911,1912,1917,1922,1927,1931,1936,1941,1946,1951,1956,1961,1965,1970,1975,1980,1985,1990,1995,1999],{"__ignoreMap":49},[53,1913,1914],{"class":55,"line":56},[53,1915,1916],{},"server {\n",[53,1918,1919],{"class":55,"line":62},[53,1920,1921],{},"    listen 443 ssl;\n",[53,1923,1924],{"class":55,"line":69},[53,1925,1926],{},"    server_name example.com;\n",[53,1928,1929],{"class":55,"line":75},[53,1930,66],{"emptyLinePlaceholder":65},[53,1932,1933],{"class":55,"line":81},[53,1934,1935],{},"    # Serve static files directly\n",[53,1937,1938],{"class":55,"line":87},[53,1939,1940],{},"    location /static/ {\n",[53,1942,1943],{"class":55,"line":93},[53,1944,1945],{},"        root /var/www/myapp;\n",[53,1947,1948],{"class":55,"line":99},[53,1949,1950],{},"        expires 1y;\n",[53,1952,1953],{"class":55,"line":105},[53,1954,1955],{},"        add_header Cache-Control \"public, immutable\";\n",[53,1957,1958],{"class":55,"line":111},[53,1959,1960],{},"    }\n",[53,1962,1963],{"class":55,"line":117},[53,1964,66],{"emptyLinePlaceholder":65},[53,1966,1967],{"class":55,"line":123},[53,1968,1969],{},"    # Forward everything else to Node.js app\n",[53,1971,1972],{"class":55,"line":129},[53,1973,1974],{},"    location / {\n",[53,1976,1977],{"class":55,"line":135},[53,1978,1979],{},"        proxy_pass http://127.0.0.1:3000;\n",[53,1981,1982],{"class":55,"line":141},[53,1983,1984],{},"        proxy_set_header Host $host;\n",[53,1986,1987],{"class":55,"line":147},[53,1988,1989],{},"        proxy_set_header X-Real-IP $remote_addr;\n",[53,1991,1992],{"class":55,"line":439},[53,1993,1994],{},"        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",[53,1996,1997],{"class":55,"line":445},[53,1998,1960],{},[53,2000,2001],{"class":55,"line":451},[53,2002,2003],{},"}\n",[16,2005,2006,2007,2010],{},"Notice ",[20,2008,2009],{},"proxy_set_header X-Real-IP $remote_addr",". When Nginx forwards the request, the app server sees Nginx's IP, not the user's IP. This header passes the real client IP to the app so it can be logged or rate-limited correctly.",[341,2012,2014],{"id":2013},"the-application-server","The Application Server",[16,2016,2017],{},"This is where your code runs. The app server (Node.js, Python/Django, PHP/Laravel, Ruby on Rails, etc.) receives the forwarded request and executes your business logic.",[16,2019,2020],{},"Here is pseudo-code for what a typical request handler does:",[44,2022,2026],{"className":2023,"code":2024,"language":2025,"meta":49,"style":49},"language-javascript shiki shiki-themes github-light","// Pseudo-code: handling GET /blog/article?id=42\n\nasync function handleArticleRequest(request) {\n    const articleId = request.query.id;\n\n    // 1. Validate input\n    if (!articleId || !isInteger(articleId)) {\n        return response(400, { error: \"Invalid article ID\" });\n    }\n\n    // 2. Check cache (Redis) first\n    const cached = await redis.get(`article:${articleId}`);\n    if (cached) {\n        return response(200, JSON.parse(cached));\n    }\n\n    // 3. Query the database\n    const article = await db.query(\n        \"SELECT * FROM articles WHERE id = ? AND published = true\",\n        [articleId]\n    );\n\n    if (!article) {\n        return response(404, { error: \"Article not found\" });\n    }\n\n    // 4. Cache the result for 1 hour\n    await redis.setex(`article:${articleId}`, 3600, JSON.stringify(article));\n\n    // 5. Send the response\n    return response(200, article);\n}\n","javascript",[20,2027,2028,2033,2037,2060,2075,2079,2084,2110,2132,2136,2140,2145,2177,2184,2208,2212,2216,2221,2241,2249,2254,2259,2263,2274,2292,2296,2300,2305,2339,2343,2349,2364],{"__ignoreMap":49},[53,2029,2030],{"class":55,"line":56},[53,2031,2032],{"class":709},"// Pseudo-code: handling GET /blog/article?id=42\n",[53,2034,2035],{"class":55,"line":62},[53,2036,66],{"emptyLinePlaceholder":65},[53,2038,2039,2043,2046,2049,2053,2057],{"class":55,"line":69},[53,2040,2042],{"class":2041},"sD7c4","async",[53,2044,2045],{"class":2041}," function",[53,2047,2048],{"class":715}," handleArticleRequest",[53,2050,2052],{"class":2051},"sgsFI","(",[53,2054,2056],{"class":2055},"sqxcx","request",[53,2058,2059],{"class":2051},") {\n",[53,2061,2062,2065,2069,2072],{"class":55,"line":75},[53,2063,2064],{"class":2041},"    const",[53,2066,2068],{"class":2067},"sYu0t"," articleId",[53,2070,2071],{"class":2041}," =",[53,2073,2074],{"class":2051}," request.query.id;\n",[53,2076,2077],{"class":55,"line":81},[53,2078,66],{"emptyLinePlaceholder":65},[53,2080,2081],{"class":55,"line":87},[53,2082,2083],{"class":709},"    // 1. Validate input\n",[53,2085,2086,2089,2092,2095,2098,2101,2104,2107],{"class":55,"line":93},[53,2087,2088],{"class":2041},"    if",[53,2090,2091],{"class":2051}," (",[53,2093,2094],{"class":2041},"!",[53,2096,2097],{"class":2051},"articleId ",[53,2099,2100],{"class":2041},"||",[53,2102,2103],{"class":2041}," !",[53,2105,2106],{"class":715},"isInteger",[53,2108,2109],{"class":2051},"(articleId)) {\n",[53,2111,2112,2115,2118,2120,2123,2126,2129],{"class":55,"line":99},[53,2113,2114],{"class":2041},"        return",[53,2116,2117],{"class":715}," response",[53,2119,2052],{"class":2051},[53,2121,2122],{"class":2067},"400",[53,2124,2125],{"class":2051},", { error: ",[53,2127,2128],{"class":719},"\"Invalid article ID\"",[53,2130,2131],{"class":2051}," });\n",[53,2133,2134],{"class":55,"line":105},[53,2135,1960],{"class":2051},[53,2137,2138],{"class":55,"line":111},[53,2139,66],{"emptyLinePlaceholder":65},[53,2141,2142],{"class":55,"line":117},[53,2143,2144],{"class":709},"    // 2. Check cache (Redis) first\n",[53,2146,2147,2149,2152,2154,2157,2160,2163,2165,2168,2171,2174],{"class":55,"line":123},[53,2148,2064],{"class":2041},[53,2150,2151],{"class":2067}," cached",[53,2153,2071],{"class":2041},[53,2155,2156],{"class":2041}," await",[53,2158,2159],{"class":2051}," redis.",[53,2161,2162],{"class":715},"get",[53,2164,2052],{"class":2051},[53,2166,2167],{"class":719},"`article:${",[53,2169,2170],{"class":2051},"articleId",[53,2172,2173],{"class":719},"}`",[53,2175,2176],{"class":2051},");\n",[53,2178,2179,2181],{"class":55,"line":129},[53,2180,2088],{"class":2041},[53,2182,2183],{"class":2051}," (cached) {\n",[53,2185,2186,2188,2190,2192,2195,2197,2200,2202,2205],{"class":55,"line":135},[53,2187,2114],{"class":2041},[53,2189,2117],{"class":715},[53,2191,2052],{"class":2051},[53,2193,2194],{"class":2067},"200",[53,2196,523],{"class":2051},[53,2198,2199],{"class":2067},"JSON",[53,2201,530],{"class":2051},[53,2203,2204],{"class":715},"parse",[53,2206,2207],{"class":2051},"(cached));\n",[53,2209,2210],{"class":55,"line":141},[53,2211,1960],{"class":2051},[53,2213,2214],{"class":55,"line":147},[53,2215,66],{"emptyLinePlaceholder":65},[53,2217,2218],{"class":55,"line":439},[53,2219,2220],{"class":709},"    // 3. Query the database\n",[53,2222,2223,2225,2228,2230,2232,2235,2238],{"class":55,"line":445},[53,2224,2064],{"class":2041},[53,2226,2227],{"class":2067}," article",[53,2229,2071],{"class":2041},[53,2231,2156],{"class":2041},[53,2233,2234],{"class":2051}," db.",[53,2236,2237],{"class":715},"query",[53,2239,2240],{"class":2051},"(\n",[53,2242,2243,2246],{"class":55,"line":451},[53,2244,2245],{"class":719},"        \"SELECT * FROM articles WHERE id = ? AND published = true\"",[53,2247,2248],{"class":2051},",\n",[53,2250,2251],{"class":55,"line":457},[53,2252,2253],{"class":2051},"        [articleId]\n",[53,2255,2256],{"class":55,"line":462},[53,2257,2258],{"class":2051},"    );\n",[53,2260,2261],{"class":55,"line":468},[53,2262,66],{"emptyLinePlaceholder":65},[53,2264,2265,2267,2269,2271],{"class":55,"line":473},[53,2266,2088],{"class":2041},[53,2268,2091],{"class":2051},[53,2270,2094],{"class":2041},[53,2272,2273],{"class":2051},"article) {\n",[53,2275,2276,2278,2280,2282,2285,2287,2290],{"class":55,"line":479},[53,2277,2114],{"class":2041},[53,2279,2117],{"class":715},[53,2281,2052],{"class":2051},[53,2283,2284],{"class":2067},"404",[53,2286,2125],{"class":2051},[53,2288,2289],{"class":719},"\"Article not found\"",[53,2291,2131],{"class":2051},[53,2293,2294],{"class":55,"line":484},[53,2295,1960],{"class":2051},[53,2297,2298],{"class":55,"line":490},[53,2299,66],{"emptyLinePlaceholder":65},[53,2301,2302],{"class":55,"line":495},[53,2303,2304],{"class":709},"    // 4. Cache the result for 1 hour\n",[53,2306,2307,2310,2312,2315,2317,2319,2321,2323,2325,2327,2329,2331,2333,2336],{"class":55,"line":501},[53,2308,2309],{"class":2041},"    await",[53,2311,2159],{"class":2051},[53,2313,2314],{"class":715},"setex",[53,2316,2052],{"class":2051},[53,2318,2167],{"class":719},[53,2320,2170],{"class":2051},[53,2322,2173],{"class":719},[53,2324,523],{"class":2051},[53,2326,689],{"class":2067},[53,2328,523],{"class":2051},[53,2330,2199],{"class":2067},[53,2332,530],{"class":2051},[53,2334,2335],{"class":715},"stringify",[53,2337,2338],{"class":2051},"(article));\n",[53,2340,2341],{"class":55,"line":506},[53,2342,66],{"emptyLinePlaceholder":65},[53,2344,2346],{"class":55,"line":2345},30,[53,2347,2348],{"class":709},"    // 5. Send the response\n",[53,2350,2352,2355,2357,2359,2361],{"class":55,"line":2351},31,[53,2353,2354],{"class":2041},"    return",[53,2356,2117],{"class":715},[53,2358,2052],{"class":2051},[53,2360,2194],{"class":2067},[53,2362,2363],{"class":2051},", article);\n",[53,2365,2367],{"class":55,"line":2366},32,[53,2368,2003],{"class":2051},[16,2370,2371],{},"Notice the caching step. Databases are relatively slow for read-heavy workloads. A cache like Redis stores frequently-read data in memory, where reads take microseconds instead of milliseconds. Well-designed applications serve the majority of read requests from cache, dramatically reducing database load.",[341,2373,2375],{"id":2374},"the-database-query","The Database Query",[16,2377,2378],{},"When the cache misses, the app talks to the database. A database server (PostgreSQL, MySQL, SQLite, MongoDB) stores data on disk, maintains indexes for fast lookups, and processes SQL queries.",[44,2380,2384],{"className":2381,"code":2382,"language":2383,"meta":49,"style":49},"language-sql shiki shiki-themes github-light","SELECT\n    a.id,\n    a.title,\n    a.body,\n    a.published_at,\n    u.name AS author_name\nFROM articles a\nJOIN users u ON u.id = a.author_id\nWHERE a.id = 42\n  AND a.published = true;\n","sql",[20,2385,2386,2391,2403,2414,2425,2436,2452,2460,2488,2504],{"__ignoreMap":49},[53,2387,2388],{"class":55,"line":56},[53,2389,2390],{"class":2041},"SELECT\n",[53,2392,2393,2396,2398,2401],{"class":55,"line":62},[53,2394,2395],{"class":2067},"    a",[53,2397,530],{"class":2051},[53,2399,2400],{"class":2067},"id",[53,2402,2248],{"class":2051},[53,2404,2405,2407,2409,2412],{"class":55,"line":69},[53,2406,2395],{"class":2067},[53,2408,530],{"class":2051},[53,2410,2411],{"class":2067},"title",[53,2413,2248],{"class":2051},[53,2415,2416,2418,2420,2423],{"class":55,"line":75},[53,2417,2395],{"class":2067},[53,2419,530],{"class":2051},[53,2421,2422],{"class":2067},"body",[53,2424,2248],{"class":2051},[53,2426,2427,2429,2431,2434],{"class":55,"line":81},[53,2428,2395],{"class":2067},[53,2430,530],{"class":2051},[53,2432,2433],{"class":2067},"published_at",[53,2435,2248],{"class":2051},[53,2437,2438,2441,2443,2446,2449],{"class":55,"line":87},[53,2439,2440],{"class":2067},"    u",[53,2442,530],{"class":2051},[53,2444,2445],{"class":2067},"name",[53,2447,2448],{"class":2041}," AS",[53,2450,2451],{"class":2051}," author_name\n",[53,2453,2454,2457],{"class":55,"line":93},[53,2455,2456],{"class":2041},"FROM",[53,2458,2459],{"class":2051}," articles a\n",[53,2461,2462,2465,2468,2471,2474,2476,2478,2480,2483,2485],{"class":55,"line":99},[53,2463,2464],{"class":2041},"JOIN",[53,2466,2467],{"class":2051}," users u ",[53,2469,2470],{"class":2041},"ON",[53,2472,2473],{"class":2067}," u",[53,2475,530],{"class":2051},[53,2477,2400],{"class":2067},[53,2479,2071],{"class":2041},[53,2481,2482],{"class":2067}," a",[53,2484,530],{"class":2051},[53,2486,2487],{"class":2067},"author_id\n",[53,2489,2490,2493,2495,2497,2499,2501],{"class":55,"line":105},[53,2491,2492],{"class":2041},"WHERE",[53,2494,2482],{"class":2067},[53,2496,530],{"class":2051},[53,2498,2400],{"class":2067},[53,2500,2071],{"class":2041},[53,2502,2503],{"class":2067}," 42\n",[53,2505,2506,2509,2511,2513,2516,2518],{"class":55,"line":111},[53,2507,2508],{"class":2041},"  AND",[53,2510,2482],{"class":2067},[53,2512,530],{"class":2051},[53,2514,2515],{"class":2067},"published",[53,2517,2071],{"class":2041},[53,2519,2520],{"class":2051}," true;\n",[16,2522,2523],{},"The database engine:",[2525,2526,2527,2530,2533,2536],"ol",{},[1397,2528,2529],{},"Parses the SQL statement",[1397,2531,2532],{},"Plans the most efficient query execution path (using indexes where available)",[1397,2534,2535],{},"Reads the relevant rows from disk (or from its own buffer cache in memory)",[1397,2537,2538],{},"Returns the result set to the application",[16,2540,2541,2542,2545],{},"Indexes are critical for performance. Without an index on ",[20,2543,2544],{},"articles.id",", the database would scan every single row in the table to find article #42. With an index (which most primary key columns have automatically), it jumps directly to the right row in microseconds.",[34,2547],{},[11,2549,2551],{"id":2550},"step-7-the-http-response","Step 7: The HTTP Response",[16,2553,2554],{},"After processing the request, the server sends back an HTTP response. Like the request, it has a structure: a status line, headers, and a body.",[341,2556,2558],{"id":2557},"http-response-structure","HTTP Response Structure",[44,2560,2562],{"className":1331,"code":2561,"language":1333,"meta":49,"style":49},"HTTP/1.1 200 OK\nContent-Type: text/html; charset=UTF-8\nContent-Encoding: gzip\nContent-Length: 12840\nCache-Control: public, max-age=3600\nETag: \"abc123def456\"\nLast-Modified: Sun, 20 Apr 2026 10:00:00 GMT\nSet-Cookie: session_id=xyz789; HttpOnly; Secure; SameSite=Strict\nX-Request-ID: req_a1b2c3d4\nStrict-Transport-Security: max-age=31536000; includeSubDomains\n\n\u003C!DOCTYPE html>\n\u003Chtml>\n...\n\u003C/html>\n",[20,2563,2564,2569,2574,2579,2584,2589,2594,2599,2604,2609,2614,2618,2623,2628,2633],{"__ignoreMap":49},[53,2565,2566],{"class":55,"line":56},[53,2567,2568],{},"HTTP/1.1 200 OK\n",[53,2570,2571],{"class":55,"line":62},[53,2572,2573],{},"Content-Type: text/html; charset=UTF-8\n",[53,2575,2576],{"class":55,"line":69},[53,2577,2578],{},"Content-Encoding: gzip\n",[53,2580,2581],{"class":55,"line":75},[53,2582,2583],{},"Content-Length: 12840\n",[53,2585,2586],{"class":55,"line":81},[53,2587,2588],{},"Cache-Control: public, max-age=3600\n",[53,2590,2591],{"class":55,"line":87},[53,2592,2593],{},"ETag: \"abc123def456\"\n",[53,2595,2596],{"class":55,"line":93},[53,2597,2598],{},"Last-Modified: Sun, 20 Apr 2026 10:00:00 GMT\n",[53,2600,2601],{"class":55,"line":99},[53,2602,2603],{},"Set-Cookie: session_id=xyz789; HttpOnly; Secure; SameSite=Strict\n",[53,2605,2606],{"class":55,"line":105},[53,2607,2608],{},"X-Request-ID: req_a1b2c3d4\n",[53,2610,2611],{"class":55,"line":111},[53,2612,2613],{},"Strict-Transport-Security: max-age=31536000; includeSubDomains\n",[53,2615,2616],{"class":55,"line":117},[53,2617,66],{"emptyLinePlaceholder":65},[53,2619,2620],{"class":55,"line":123},[53,2621,2622],{},"\u003C!DOCTYPE html>\n",[53,2624,2625],{"class":55,"line":129},[53,2626,2627],{},"\u003Chtml>\n",[53,2629,2630],{"class":55,"line":135},[53,2631,2632],{},"...\n",[53,2634,2635],{"class":55,"line":141},[53,2636,2637],{},"\u003C/html>\n",[341,2639,2641],{"id":2640},"http-status-codes","HTTP Status Codes",[16,2643,2644],{},"The three-digit status code tells the browser whether the request succeeded and what kind of result to expect:",[44,2646,2648],{"className":46,"code":2647,"language":48,"meta":49,"style":49},"1xx  Informational\n  100 Continue            : server got headers, client should send body\n\n2xx  Success\n  200 OK                  : standard success\n  201 Created             : resource was created (after POST)\n  204 No Content          : success but no body (after DELETE)\n\n3xx  Redirection\n  301 Moved Permanently   : URL changed forever (update your bookmarks/links)\n  302 Found               : temporary redirect\n  304 Not Modified        : cached version is still fresh (no body sent)\n\n4xx  Client Errors\n  400 Bad Request         : malformed request\n  401 Unauthorized        : authentication required\n  403 Forbidden           : authenticated but not allowed\n  404 Not Found           : resource does not exist\n  429 Too Many Requests   : rate limited\n\n5xx  Server Errors\n  500 Internal Server Error   : something crashed on the server\n  502 Bad Gateway             : Nginx could not reach the app server\n  503 Service Unavailable     : server is overloaded or down\n  504 Gateway Timeout         : app server took too long to respond\n",[20,2649,2650,2655,2660,2664,2669,2674,2679,2684,2688,2693,2698,2703,2708,2712,2717,2722,2727,2732,2737,2742,2746,2751,2756,2761,2766],{"__ignoreMap":49},[53,2651,2652],{"class":55,"line":56},[53,2653,2654],{},"1xx  Informational\n",[53,2656,2657],{"class":55,"line":62},[53,2658,2659],{},"  100 Continue            : server got headers, client should send body\n",[53,2661,2662],{"class":55,"line":69},[53,2663,66],{"emptyLinePlaceholder":65},[53,2665,2666],{"class":55,"line":75},[53,2667,2668],{},"2xx  Success\n",[53,2670,2671],{"class":55,"line":81},[53,2672,2673],{},"  200 OK                  : standard success\n",[53,2675,2676],{"class":55,"line":87},[53,2677,2678],{},"  201 Created             : resource was created (after POST)\n",[53,2680,2681],{"class":55,"line":93},[53,2682,2683],{},"  204 No Content          : success but no body (after DELETE)\n",[53,2685,2686],{"class":55,"line":99},[53,2687,66],{"emptyLinePlaceholder":65},[53,2689,2690],{"class":55,"line":105},[53,2691,2692],{},"3xx  Redirection\n",[53,2694,2695],{"class":55,"line":111},[53,2696,2697],{},"  301 Moved Permanently   : URL changed forever (update your bookmarks/links)\n",[53,2699,2700],{"class":55,"line":117},[53,2701,2702],{},"  302 Found               : temporary redirect\n",[53,2704,2705],{"class":55,"line":123},[53,2706,2707],{},"  304 Not Modified        : cached version is still fresh (no body sent)\n",[53,2709,2710],{"class":55,"line":129},[53,2711,66],{"emptyLinePlaceholder":65},[53,2713,2714],{"class":55,"line":135},[53,2715,2716],{},"4xx  Client Errors\n",[53,2718,2719],{"class":55,"line":141},[53,2720,2721],{},"  400 Bad Request         : malformed request\n",[53,2723,2724],{"class":55,"line":147},[53,2725,2726],{},"  401 Unauthorized        : authentication required\n",[53,2728,2729],{"class":55,"line":439},[53,2730,2731],{},"  403 Forbidden           : authenticated but not allowed\n",[53,2733,2734],{"class":55,"line":445},[53,2735,2736],{},"  404 Not Found           : resource does not exist\n",[53,2738,2739],{"class":55,"line":451},[53,2740,2741],{},"  429 Too Many Requests   : rate limited\n",[53,2743,2744],{"class":55,"line":457},[53,2745,66],{"emptyLinePlaceholder":65},[53,2747,2748],{"class":55,"line":462},[53,2749,2750],{},"5xx  Server Errors\n",[53,2752,2753],{"class":55,"line":468},[53,2754,2755],{},"  500 Internal Server Error   : something crashed on the server\n",[53,2757,2758],{"class":55,"line":473},[53,2759,2760],{},"  502 Bad Gateway             : Nginx could not reach the app server\n",[53,2762,2763],{"class":55,"line":479},[53,2764,2765],{},"  503 Service Unavailable     : server is overloaded or down\n",[53,2767,2768],{"class":55,"line":484},[53,2769,2770],{},"  504 Gateway Timeout         : app server took too long to respond\n",[16,2772,2773],{},"The difference between 401 and 403 trips many developers up:",[1394,2775,2776,2782],{},[1397,2777,2778,2781],{},[516,2779,2780],{},"401:"," \"Who are you? Please log in first.\"",[1397,2783,2784,2787],{},[516,2785,2786],{},"403:"," \"I know who you are. You are just not allowed to do this.\"",[341,2789,2791],{"id":2790},"important-response-headers","Important Response Headers",[16,2793,2794,2797,2798,2801,2802,2805,2806,2809],{},[516,2795,2796],{},"Content-Type:"," Tells the browser how to interpret the body. ",[20,2799,2800],{},"text/html"," means render as HTML. ",[20,2803,2804],{},"application/json"," means parse as JSON. ",[20,2807,2808],{},"image/png"," means display as an image. Getting this wrong causes browsers to display raw text instead of rendering a page.",[16,2811,2812,2814],{},[516,2813,1461],{}," Controls caching behavior for both browsers and CDNs:",[44,2816,2818],{"className":46,"code":2817,"language":48,"meta":49,"style":49},"Cache-Control: public, max-age=86400\n  (anyone can cache this for 24 hours)\n\nCache-Control: private, max-age=300\n  (only the browser can cache it, not CDNs, for 5 minutes)\n\nCache-Control: no-store\n  (never cache this, for sensitive data like banking pages)\n",[20,2819,2820,2825,2830,2834,2839,2844,2848,2853],{"__ignoreMap":49},[53,2821,2822],{"class":55,"line":56},[53,2823,2824],{},"Cache-Control: public, max-age=86400\n",[53,2826,2827],{"class":55,"line":62},[53,2828,2829],{},"  (anyone can cache this for 24 hours)\n",[53,2831,2832],{"class":55,"line":69},[53,2833,66],{"emptyLinePlaceholder":65},[53,2835,2836],{"class":55,"line":75},[53,2837,2838],{},"Cache-Control: private, max-age=300\n",[53,2840,2841],{"class":55,"line":81},[53,2842,2843],{},"  (only the browser can cache it, not CDNs, for 5 minutes)\n",[53,2845,2846],{"class":55,"line":87},[53,2847,66],{"emptyLinePlaceholder":65},[53,2849,2850],{"class":55,"line":93},[53,2851,2852],{},"Cache-Control: no-store\n",[53,2854,2855],{"class":55,"line":99},[53,2856,2857],{},"  (never cache this, for sensitive data like banking pages)\n",[16,2859,2860,2863,2864,2867,2868,2871],{},[516,2861,2862],{},"ETag:"," A fingerprint of the content. When the browser has a cached copy and wants to check if it is still fresh, it sends ",[20,2865,2866],{},"If-None-Match: \"abc123def456\"",". The server checks: if content has not changed, it responds with ",[20,2869,2870],{},"304 Not Modified"," and no body. This saves bandwidth significantly.",[16,2873,2874,2877],{},[516,2875,2876],{},"Set-Cookie:"," Sets cookies in the browser. The security flags matter:",[44,2879,2880],{"className":1331,"code":2603,"language":1333,"meta":49,"style":49},[20,2881,2882],{"__ignoreMap":49},[53,2883,2884],{"class":55,"line":56},[53,2885,2603],{},[1394,2887,2888,2894,2900],{},[1397,2889,2890,2893],{},[20,2891,2892],{},"HttpOnly",": JavaScript cannot read this cookie (prevents XSS stealing sessions)",[1397,2895,2896,2899],{},[20,2897,2898],{},"Secure",": Only sent over HTTPS connections",[1397,2901,2902,2905],{},[20,2903,2904],{},"SameSite=Strict",": Not sent with cross-site requests (prevents CSRF attacks)",[16,2907,2908,2911,2912,2915,2916,2919],{},[516,2909,2910],{},"Strict-Transport-Security (HSTS):"," Tells the browser to always use HTTPS for this domain, even if someone types ",[20,2913,2914],{},"http://",". The ",[20,2917,2918],{},"max-age=31536000"," means this rule should be remembered for 1 year.",[34,2921],{},[11,2923,2925],{"id":2924},"step-8-browser-rendering-turning-bytes-into-pixels","Step 8: Browser Rendering (Turning Bytes into Pixels)",[16,2927,2928,2929,2932],{},"The browser has received the HTTP response. It now needs to turn raw bytes into a visual webpage. This process is called the ",[516,2930,2931],{},"Critical Rendering Path"," and it has several distinct stages.",[341,2934,2936],{"id":2935},"the-full-rendering-pipeline","The Full Rendering Pipeline",[44,2938,2940],{"className":46,"code":2939,"language":48,"meta":49,"style":49},"  Bytes (raw data from network)\n      |\n      v\n  Characters (decoded with UTF-8)\n      |\n      v\n  Tokens (\u003C/html>, \u003Chead>, \u003Cbody>, etc.)\n      |\n      +------------------------+\n      |                        |\n      v                        v\n    DOM                      CSSOM\n  (Document Object          (CSS Object\n   Model)                    Model)\n      |                        |\n      +----------+-------------+\n                 |\n                 v\n           Render Tree\n      (visible nodes with styles)\n                 |\n                 v\n              Layout\n      (calculate sizes and positions)\n                 |\n                 v\n              Paint\n      (draw pixels to layers)\n                 |\n                 v\n           Compositing\n      (combine layers into final frame)\n                 |\n                 v\n         Screen Display\n",[20,2941,2942,2947,2951,2955,2960,2964,2968,2973,2977,2982,2987,2992,2997,3002,3007,3011,3016,3021,3026,3031,3036,3040,3044,3049,3054,3058,3062,3067,3072,3076,3080,3085,3090,3095,3100],{"__ignoreMap":49},[53,2943,2944],{"class":55,"line":56},[53,2945,2946],{},"  Bytes (raw data from network)\n",[53,2948,2949],{"class":55,"line":62},[53,2950,1235],{},[53,2952,2953],{"class":55,"line":69},[53,2954,1783],{},[53,2956,2957],{"class":55,"line":75},[53,2958,2959],{},"  Characters (decoded with UTF-8)\n",[53,2961,2962],{"class":55,"line":81},[53,2963,1235],{},[53,2965,2966],{"class":55,"line":87},[53,2967,1783],{},[53,2969,2970],{"class":55,"line":93},[53,2971,2972],{},"  Tokens (\u003C/html>, \u003Chead>, \u003Cbody>, etc.)\n",[53,2974,2975],{"class":55,"line":99},[53,2976,1235],{},[53,2978,2979],{"class":55,"line":105},[53,2980,2981],{},"      +------------------------+\n",[53,2983,2984],{"class":55,"line":111},[53,2985,2986],{},"      |                        |\n",[53,2988,2989],{"class":55,"line":117},[53,2990,2991],{},"      v                        v\n",[53,2993,2994],{"class":55,"line":123},[53,2995,2996],{},"    DOM                      CSSOM\n",[53,2998,2999],{"class":55,"line":129},[53,3000,3001],{},"  (Document Object          (CSS Object\n",[53,3003,3004],{"class":55,"line":135},[53,3005,3006],{},"   Model)                    Model)\n",[53,3008,3009],{"class":55,"line":141},[53,3010,2986],{},[53,3012,3013],{"class":55,"line":147},[53,3014,3015],{},"      +----------+-------------+\n",[53,3017,3018],{"class":55,"line":439},[53,3019,3020],{},"                 |\n",[53,3022,3023],{"class":55,"line":445},[53,3024,3025],{},"                 v\n",[53,3027,3028],{"class":55,"line":451},[53,3029,3030],{},"           Render Tree\n",[53,3032,3033],{"class":55,"line":457},[53,3034,3035],{},"      (visible nodes with styles)\n",[53,3037,3038],{"class":55,"line":462},[53,3039,3020],{},[53,3041,3042],{"class":55,"line":468},[53,3043,3025],{},[53,3045,3046],{"class":55,"line":473},[53,3047,3048],{},"              Layout\n",[53,3050,3051],{"class":55,"line":479},[53,3052,3053],{},"      (calculate sizes and positions)\n",[53,3055,3056],{"class":55,"line":484},[53,3057,3020],{},[53,3059,3060],{"class":55,"line":490},[53,3061,3025],{},[53,3063,3064],{"class":55,"line":495},[53,3065,3066],{},"              Paint\n",[53,3068,3069],{"class":55,"line":501},[53,3070,3071],{},"      (draw pixels to layers)\n",[53,3073,3074],{"class":55,"line":506},[53,3075,3020],{},[53,3077,3078],{"class":55,"line":2345},[53,3079,3025],{},[53,3081,3082],{"class":55,"line":2351},[53,3083,3084],{},"           Compositing\n",[53,3086,3087],{"class":55,"line":2366},[53,3088,3089],{},"      (combine layers into final frame)\n",[53,3091,3093],{"class":55,"line":3092},33,[53,3094,3020],{},[53,3096,3098],{"class":55,"line":3097},34,[53,3099,3025],{},[53,3101,3103],{"class":55,"line":3102},35,[53,3104,3105],{},"         Screen Display\n",[341,3107,3109],{"id":3108},"parsing-html-building-the-dom","Parsing HTML: Building the DOM",[16,3111,3112,3113,3116],{},"The browser reads the HTML bytes and tokenizes them into a tree structure called the ",[516,3114,3115],{},"Document Object Model (DOM)",". Each HTML tag becomes a node in the tree.",[44,3118,3122],{"className":3119,"code":3120,"language":3121,"meta":49,"style":49},"language-html shiki shiki-themes github-light","\u003C!DOCTYPE html>\n\u003Chtml>\n  \u003Chead>\n    \u003Ctitle>My Page\u003C/title>\n  \u003C/head>\n  \u003Cbody>\n    \u003Ch1>Hello World\u003C/h1>\n    \u003Cp>A paragraph.\u003C/p>\n  \u003C/body>\n\u003C/html>\n","html",[20,3123,3124,3139,3148,3158,3172,3181,3189,3203,3216,3224],{"__ignoreMap":49},[53,3125,3126,3129,3133,3136],{"class":55,"line":56},[53,3127,3128],{"class":2051},"\u003C!",[53,3130,3132],{"class":3131},"shJU0","DOCTYPE",[53,3134,3135],{"class":715}," html",[53,3137,3138],{"class":2051},">\n",[53,3140,3141,3144,3146],{"class":55,"line":62},[53,3142,3143],{"class":2051},"\u003C",[53,3145,3121],{"class":3131},[53,3147,3138],{"class":2051},[53,3149,3150,3153,3156],{"class":55,"line":69},[53,3151,3152],{"class":2051},"  \u003C",[53,3154,3155],{"class":3131},"head",[53,3157,3138],{"class":2051},[53,3159,3160,3163,3165,3168,3170],{"class":55,"line":75},[53,3161,3162],{"class":2051},"    \u003C",[53,3164,2411],{"class":3131},[53,3166,3167],{"class":2051},">My Page\u003C/",[53,3169,2411],{"class":3131},[53,3171,3138],{"class":2051},[53,3173,3174,3177,3179],{"class":55,"line":81},[53,3175,3176],{"class":2051},"  \u003C/",[53,3178,3155],{"class":3131},[53,3180,3138],{"class":2051},[53,3182,3183,3185,3187],{"class":55,"line":87},[53,3184,3152],{"class":2051},[53,3186,2422],{"class":3131},[53,3188,3138],{"class":2051},[53,3190,3191,3193,3196,3199,3201],{"class":55,"line":93},[53,3192,3162],{"class":2051},[53,3194,3195],{"class":3131},"h1",[53,3197,3198],{"class":2051},">Hello World\u003C/",[53,3200,3195],{"class":3131},[53,3202,3138],{"class":2051},[53,3204,3205,3207,3209,3212,3214],{"class":55,"line":99},[53,3206,3162],{"class":2051},[53,3208,16],{"class":3131},[53,3210,3211],{"class":2051},">A paragraph.\u003C/",[53,3213,16],{"class":3131},[53,3215,3138],{"class":2051},[53,3217,3218,3220,3222],{"class":55,"line":105},[53,3219,3176],{"class":2051},[53,3221,2422],{"class":3131},[53,3223,3138],{"class":2051},[53,3225,3226,3229,3231],{"class":55,"line":111},[53,3227,3228],{"class":2051},"\u003C/",[53,3230,3121],{"class":3131},[53,3232,3138],{"class":2051},[16,3234,3235],{},"This becomes:",[44,3237,3239],{"className":46,"code":3238,"language":48,"meta":49,"style":49},"Document\n  └── html\n        ├── head\n        │     └── title\n        │           └── \"My Page\"\n        └── body\n              ├── h1\n              │     └── \"Hello World\"\n              └── p\n                    └── \"A paragraph.\"\n",[20,3240,3241,3246,3251,3256,3261,3266,3271,3276,3281,3286],{"__ignoreMap":49},[53,3242,3243],{"class":55,"line":56},[53,3244,3245],{},"Document\n",[53,3247,3248],{"class":55,"line":62},[53,3249,3250],{},"  └── html\n",[53,3252,3253],{"class":55,"line":69},[53,3254,3255],{},"        ├── head\n",[53,3257,3258],{"class":55,"line":75},[53,3259,3260],{},"        │     └── title\n",[53,3262,3263],{"class":55,"line":81},[53,3264,3265],{},"        │           └── \"My Page\"\n",[53,3267,3268],{"class":55,"line":87},[53,3269,3270],{},"        └── body\n",[53,3272,3273],{"class":55,"line":93},[53,3274,3275],{},"              ├── h1\n",[53,3277,3278],{"class":55,"line":99},[53,3279,3280],{},"              │     └── \"Hello World\"\n",[53,3282,3283],{"class":55,"line":105},[53,3284,3285],{},"              └── p\n",[53,3287,3288],{"class":55,"line":111},[53,3289,3290],{},"                    └── \"A paragraph.\"\n",[341,3292,3294],{"id":3293},"parsing-css-building-the-cssom","Parsing CSS: Building the CSSOM",[16,3296,3297,3298,3301],{},"Simultaneously (or as CSS files arrive), the browser parses CSS into the ",[516,3299,3300],{},"CSS Object Model (CSSOM)",", a similar tree structure that maps selectors to computed styles.",[44,3303,3307],{"className":3304,"code":3305,"language":3306,"meta":49,"style":49},"language-css shiki shiki-themes github-light","body { font-family: sans-serif; }\nh1   { color: blue; font-size: 2em; }\np    { color: gray; }\n","css",[20,3308,3309,3328,3359],{"__ignoreMap":49},[53,3310,3311,3313,3316,3319,3322,3325],{"class":55,"line":56},[53,3312,2422],{"class":3131},[53,3314,3315],{"class":2051}," { ",[53,3317,3318],{"class":2067},"font-family",[53,3320,3321],{"class":2051},": ",[53,3323,3324],{"class":2067},"sans-serif",[53,3326,3327],{"class":2051},"; }\n",[53,3329,3330,3332,3335,3338,3340,3343,3346,3349,3351,3354,3357],{"class":55,"line":62},[53,3331,3195],{"class":3131},[53,3333,3334],{"class":2051},"   { ",[53,3336,3337],{"class":2067},"color",[53,3339,3321],{"class":2051},[53,3341,3342],{"class":2067},"blue",[53,3344,3345],{"class":2051},"; ",[53,3347,3348],{"class":2067},"font-size",[53,3350,3321],{"class":2051},[53,3352,3353],{"class":2067},"2",[53,3355,3356],{"class":2041},"em",[53,3358,3327],{"class":2051},[53,3360,3361,3363,3366,3368,3370,3373],{"class":55,"line":69},[53,3362,16],{"class":3131},[53,3364,3365],{"class":2051},"    { ",[53,3367,3337],{"class":2067},[53,3369,3321],{"class":2051},[53,3371,3372],{"class":2067},"gray",[53,3374,3327],{"class":2051},[16,3376,3377],{},"Becomes:",[44,3379,3381],{"className":46,"code":3380,"language":48,"meta":49,"style":49},"body\n  ├── font-family: sans-serif\n  └── h1\n        ├── color: blue\n        └── font-size: 2em\n  └── p\n        └── color: gray\n",[20,3382,3383,3388,3393,3398,3403,3408,3413],{"__ignoreMap":49},[53,3384,3385],{"class":55,"line":56},[53,3386,3387],{},"body\n",[53,3389,3390],{"class":55,"line":62},[53,3391,3392],{},"  ├── font-family: sans-serif\n",[53,3394,3395],{"class":55,"line":69},[53,3396,3397],{},"  └── h1\n",[53,3399,3400],{"class":55,"line":75},[53,3401,3402],{},"        ├── color: blue\n",[53,3404,3405],{"class":55,"line":81},[53,3406,3407],{},"        └── font-size: 2em\n",[53,3409,3410],{"class":55,"line":87},[53,3411,3412],{},"  └── p\n",[53,3414,3415],{"class":55,"line":93},[53,3416,3417],{},"        └── color: gray\n",[16,3419,3420,3421,3424,3425,3428,3429,3432],{},"CSS is ",[516,3422,3423],{},"render-blocking",": the browser cannot display anything until all CSS is downloaded and parsed. This is why you put ",[20,3426,3427],{},"\u003Clink rel=\"stylesheet\">"," in the ",[20,3430,3431],{},"\u003Chead>",": you want CSS to arrive before the browser starts painting. A slow CSS file delays the entire page.",[341,3434,3436],{"id":3435},"javascript-the-complication","JavaScript: The Complication",[16,3438,3439,3440,3443,3444,3447,3448,530],{},"When the HTML parser encounters a ",[20,3441,3442],{},"\u003Cscript>"," tag, by default it ",[516,3445,3446],{},"stops parsing HTML",", downloads the script, executes it (because JS can modify the DOM), and only then resumes parsing. This is called ",[516,3449,3450],{},"parser blocking",[44,3452,3454],{"className":3119,"code":3453,"language":3121,"meta":49,"style":49},"\u003C!-- Blocks HTML parsing until script loads and executes -->\n\u003Cscript src=\"analytics.js\">\u003C/script>\n\n\u003C!-- async: downloads in parallel, executes when ready (order not guaranteed) -->\n\u003Cscript src=\"analytics.js\" async>\u003C/script>\n\n\u003C!-- defer: downloads in parallel, executes after HTML is parsed (order preserved) -->\n\u003Cscript src=\"main.js\" defer>\u003C/script>\n",[20,3455,3456,3461,3484,3488,3493,3514,3518,3523],{"__ignoreMap":49},[53,3457,3458],{"class":55,"line":56},[53,3459,3460],{"class":709},"\u003C!-- Blocks HTML parsing until script loads and executes -->\n",[53,3462,3463,3465,3468,3471,3474,3477,3480,3482],{"class":55,"line":62},[53,3464,3143],{"class":2051},[53,3466,3467],{"class":3131},"script",[53,3469,3470],{"class":715}," src",[53,3472,3473],{"class":2051},"=",[53,3475,3476],{"class":719},"\"analytics.js\"",[53,3478,3479],{"class":2051},">\u003C/",[53,3481,3467],{"class":3131},[53,3483,3138],{"class":2051},[53,3485,3486],{"class":55,"line":69},[53,3487,66],{"emptyLinePlaceholder":65},[53,3489,3490],{"class":55,"line":75},[53,3491,3492],{"class":709},"\u003C!-- async: downloads in parallel, executes when ready (order not guaranteed) -->\n",[53,3494,3495,3497,3499,3501,3503,3505,3508,3510,3512],{"class":55,"line":81},[53,3496,3143],{"class":2051},[53,3498,3467],{"class":3131},[53,3500,3470],{"class":715},[53,3502,3473],{"class":2051},[53,3504,3476],{"class":719},[53,3506,3507],{"class":715}," async",[53,3509,3479],{"class":2051},[53,3511,3467],{"class":3131},[53,3513,3138],{"class":2051},[53,3515,3516],{"class":55,"line":87},[53,3517,66],{"emptyLinePlaceholder":65},[53,3519,3520],{"class":55,"line":93},[53,3521,3522],{"class":709},"\u003C!-- defer: downloads in parallel, executes after HTML is parsed (order preserved) -->\n",[53,3524,3525,3527,3529,3531,3533,3536,3539,3541,3543],{"class":55,"line":99},[53,3526,3143],{"class":2051},[53,3528,3467],{"class":3131},[53,3530,3470],{"class":715},[53,3532,3473],{"class":2051},[53,3534,3535],{"class":719},"\"main.js\"",[53,3537,3538],{"class":715}," defer",[53,3540,3479],{"class":2051},[53,3542,3467],{"class":3131},[53,3544,3138],{"class":2051},[16,3546,3547,3548,3550,3551,3554,3555,3558,3559,3561],{},"Best practice: put ",[20,3549,3442],{}," tags at the end of ",[20,3552,3553],{},"\u003Cbody>",", or use ",[20,3556,3557],{},"defer"," for application scripts and ",[20,3560,2042],{}," for independent scripts like analytics.",[341,3563,3565],{"id":3564},"the-render-tree-combining-dom-and-cssom","The Render Tree: Combining DOM and CSSOM",[16,3567,3568,3569,3572],{},"The browser combines the DOM and CSSOM into a ",[516,3570,3571],{},"Render Tree",". This tree contains only the visible elements, with their computed styles attached.",[16,3574,3575,3576,523,3579,523,3581,523,3583,3586,3587,3590],{},"Elements that are hidden (",[20,3577,3578],{},"display: none",[20,3580,3431],{},[20,3582,3442],{},[20,3584,3585],{},"\u003Cstyle>",") are excluded from the Render Tree. Elements that are invisible but still occupy space (",[20,3588,3589],{},"visibility: hidden",") are included.",[341,3592,3594],{"id":3593},"layout-calculating-geometry","Layout: Calculating Geometry",[16,3596,3597,3598,3601],{},"With the Render Tree, the browser calculates the exact position and size of every element: this is the ",[516,3599,3600],{},"Layout"," stage (also called Reflow).",[16,3603,3604],{},"The browser considers:",[1394,3606,3607,3610,3613,3616],{},[1397,3608,3609],{},"The viewport size (window width and height)",[1397,3611,3612],{},"The box model (margin, border, padding, content)",[1397,3614,3615],{},"Flexbox and Grid rules",[1397,3617,3618],{},"Relative and absolute positioning",[16,3620,3621],{},"Layout is expensive because changing one element's size can affect everything around it. This is why causing layout \"thrash\" in JavaScript (alternating reads and writes to the DOM in a loop) is a significant performance problem.",[341,3623,3625],{"id":3624},"paint-and-compositing-drawing-pixels","Paint and Compositing: Drawing Pixels",[16,3627,3628,3629,3632],{},"After layout, the browser knows where everything goes. Now it ",[516,3630,3631],{},"paints",", filling in the pixels for each element's background, text, borders, shadows, and images.",[16,3634,3635,3636,3639,3640,3643],{},"Modern browsers split the page into ",[516,3637,3638],{},"layers"," and paint each one independently. A fixed navigation bar is on its own layer. Animated elements get their own layers. The GPU then ",[516,3641,3642],{},"composites"," all layers into the final image you see.",[16,3645,3646],{},"Properties that trigger only compositing (and are therefore very fast to animate):",[1394,3648,3649,3654],{},[1397,3650,3651],{},[20,3652,3653],{},"transform: translate(), scale(), rotate()",[1397,3655,3656],{},[20,3657,3658],{},"opacity",[16,3660,3661],{},"Properties that trigger layout (very expensive to animate):",[1394,3663,3664],{},[1397,3665,3666,523,3669,523,3672,523,3675,523,3678,523,3681],{},[20,3667,3668],{},"width",[20,3670,3671],{},"height",[20,3673,3674],{},"margin",[20,3676,3677],{},"padding",[20,3679,3680],{},"top",[20,3682,3683],{},"left",[16,3685,3686,3687,3690,3691,319,3693,530],{},"This is why performant CSS animations use ",[20,3688,3689],{},"transform"," instead of changing ",[20,3692,3683],{},[20,3694,3680],{},[34,3696],{},[11,3698,3700],{"id":3699},"step-9-sub-resources-and-the-waterfall","Step 9: Sub-resources and the Waterfall",[16,3702,3703],{},"Loading the initial HTML is just the beginning. The HTML contains references to many other resources: CSS files, JavaScript files, images, fonts, icons. The browser discovers these references as it parses the HTML and fetches them in parallel.",[341,3705,3707],{"id":3706},"the-network-waterfall","The Network Waterfall",[16,3709,3710],{},"A typical web page load looks like this in the browser's Network panel:",[44,3712,3714],{"className":46,"code":3713,"language":48,"meta":49,"style":49},"0ms     100ms    200ms    300ms    400ms    500ms    600ms\n|--------|--------|--------|--------|--------|--------|\n                                                        \n[DNS]                    \n      [TCP+TLS]           \n               [HTML  ]   \n               [CSS1     ]\n               [CSS2     ]\n                    [JS1          ]\n                    [JS2          ]\n                         [logo.png     ]\n                         [hero.jpg             ]\n                         [font.woff2       ]\n                              [analytics.js    ]\n                                        |\n                                   Page ready!\n",[20,3715,3716,3721,3726,3731,3736,3741,3746,3751,3756,3761,3766,3771,3776,3781,3786,3791],{"__ignoreMap":49},[53,3717,3718],{"class":55,"line":56},[53,3719,3720],{},"0ms     100ms    200ms    300ms    400ms    500ms    600ms\n",[53,3722,3723],{"class":55,"line":62},[53,3724,3725],{},"|--------|--------|--------|--------|--------|--------|\n",[53,3727,3728],{"class":55,"line":69},[53,3729,3730],{},"                                                        \n",[53,3732,3733],{"class":55,"line":75},[53,3734,3735],{},"[DNS]                    \n",[53,3737,3738],{"class":55,"line":81},[53,3739,3740],{},"      [TCP+TLS]           \n",[53,3742,3743],{"class":55,"line":87},[53,3744,3745],{},"               [HTML  ]   \n",[53,3747,3748],{"class":55,"line":93},[53,3749,3750],{},"               [CSS1     ]\n",[53,3752,3753],{"class":55,"line":99},[53,3754,3755],{},"               [CSS2     ]\n",[53,3757,3758],{"class":55,"line":105},[53,3759,3760],{},"                    [JS1          ]\n",[53,3762,3763],{"class":55,"line":111},[53,3764,3765],{},"                    [JS2          ]\n",[53,3767,3768],{"class":55,"line":117},[53,3769,3770],{},"                         [logo.png     ]\n",[53,3772,3773],{"class":55,"line":123},[53,3774,3775],{},"                         [hero.jpg             ]\n",[53,3777,3778],{"class":55,"line":129},[53,3779,3780],{},"                         [font.woff2       ]\n",[53,3782,3783],{"class":55,"line":135},[53,3784,3785],{},"                              [analytics.js    ]\n",[53,3787,3788],{"class":55,"line":141},[53,3789,3790],{},"                                        |\n",[53,3792,3793],{"class":55,"line":147},[53,3794,3795],{},"                                   Page ready!\n",[16,3797,3798],{},"Each resource requires the browser to:",[2525,3800,3801,3804,3807,3810,3813,3816,3819,3822],{},[1397,3802,3803],{},"Parse the URL in the HTML",[1397,3805,3806],{},"Check its local cache",[1397,3808,3809],{},"Open a TCP connection (or reuse an existing one with Keep-Alive)",[1397,3811,3812],{},"Perform a TLS handshake (for new connections)",[1397,3814,3815],{},"Send the HTTP request",[1397,3817,3818],{},"Wait for the response",[1397,3820,3821],{},"Download the body",[1397,3823,3824],{},"Parse/decode the resource",[16,3826,3827],{},"HTTP/2 helps by multiplexing many requests over one connection. But network round trips still cost time.",[341,3829,3831],{"id":3830},"critical-resources-vs-non-critical-resources","Critical Resources vs Non-Critical Resources",[16,3833,3834],{},"Not all resources are equal. Some block rendering:",[16,3836,3837,3840,3841,3843,3844,3846],{},[516,3838,3839],{},"Render-blocking resources:"," CSS in ",[20,3842,3431],{},", synchronous ",[20,3845,3442],{}," tags. The browser cannot paint anything until these are processed.",[16,3848,3849,3852,3853,3855,3856,3858],{},[516,3850,3851],{},"Non-blocking resources:"," Images, ",[20,3854,2042],{},"/",[20,3857,3557],{}," scripts, resources loaded lazily. The browser can paint the page and load these in the background.",[16,3860,3861],{},"Performance optimization is largely about minimizing the amount of render-blocking work the browser must do before it can show the user something.",[34,3863],{},[11,3865,3867],{"id":3866},"step-10-caching-making-everything-faster","Step 10: Caching (Making Everything Faster)",[16,3869,3870],{},"A full round trip from browser to server and back has costs: network latency, DNS lookup, TCP handshake, TLS negotiation, server processing time. Caches exist at multiple layers to avoid repeating this work.",[341,3872,3874],{"id":3873},"the-caching-layers","The Caching Layers",[44,3876,3878],{"className":46,"code":3877,"language":48,"meta":49,"style":49},"User\n  |\n  +--> Browser Cache\n  |      (stores responses on disk)\n  |\n  +--> Service Worker Cache\n  |      (programmable cache in the browser)\n  |\n  +--> CDN (Content Delivery Network)\n  |      (caches at edge locations near users)\n  |\n  +--> Reverse Proxy Cache (Nginx, Varnish)\n  |      (caches at the server edge)\n  |\n  +--> Application Cache (Redis, Memcached)\n  |      (caches database query results)\n  |\n  +--> Database Buffer Cache\n         (database keeps hot data in memory)\n",[20,3879,3880,3885,3890,3895,3900,3904,3909,3914,3918,3923,3928,3932,3937,3942,3946,3951,3956,3960,3965],{"__ignoreMap":49},[53,3881,3882],{"class":55,"line":56},[53,3883,3884],{},"User\n",[53,3886,3887],{"class":55,"line":62},[53,3888,3889],{},"  |\n",[53,3891,3892],{"class":55,"line":69},[53,3893,3894],{},"  +--> Browser Cache\n",[53,3896,3897],{"class":55,"line":75},[53,3898,3899],{},"  |      (stores responses on disk)\n",[53,3901,3902],{"class":55,"line":81},[53,3903,3889],{},[53,3905,3906],{"class":55,"line":87},[53,3907,3908],{},"  +--> Service Worker Cache\n",[53,3910,3911],{"class":55,"line":93},[53,3912,3913],{},"  |      (programmable cache in the browser)\n",[53,3915,3916],{"class":55,"line":99},[53,3917,3889],{},[53,3919,3920],{"class":55,"line":105},[53,3921,3922],{},"  +--> CDN (Content Delivery Network)\n",[53,3924,3925],{"class":55,"line":111},[53,3926,3927],{},"  |      (caches at edge locations near users)\n",[53,3929,3930],{"class":55,"line":117},[53,3931,3889],{},[53,3933,3934],{"class":55,"line":123},[53,3935,3936],{},"  +--> Reverse Proxy Cache (Nginx, Varnish)\n",[53,3938,3939],{"class":55,"line":129},[53,3940,3941],{},"  |      (caches at the server edge)\n",[53,3943,3944],{"class":55,"line":135},[53,3945,3889],{},[53,3947,3948],{"class":55,"line":141},[53,3949,3950],{},"  +--> Application Cache (Redis, Memcached)\n",[53,3952,3953],{"class":55,"line":147},[53,3954,3955],{},"  |      (caches database query results)\n",[53,3957,3958],{"class":55,"line":439},[53,3959,3889],{},[53,3961,3962],{"class":55,"line":445},[53,3963,3964],{},"  +--> Database Buffer Cache\n",[53,3966,3967],{"class":55,"line":451},[53,3968,3969],{},"         (database keeps hot data in memory)\n",[341,3971,3973],{"id":3972},"browser-caching-in-detail","Browser Caching in Detail",[16,3975,3976],{},"The browser stores downloaded resources locally. On the next visit, before making a network request, it checks:",[16,3978,3979,3982,3983,3986],{},[516,3980,3981],{},"Is the resource still fresh?"," (Has the ",[20,3984,3985],{},"max-age"," elapsed?)",[1394,3988,3989,3992],{},[1397,3990,3991],{},"Yes: Use cached copy. No network request at all. Instant.",[1397,3993,3994,3995,3998,3999,1446,4002],{},"No: Send a ",[516,3996,3997],{},"conditional request"," with ",[20,4000,4001],{},"If-None-Match: \"etag-value\"",[20,4003,4004],{},"If-Modified-Since: date",[16,4006,4007,4010],{},[516,4008,4009],{},"Did the server say the cache is still valid?"," (304 Not Modified)",[1394,4012,4013,4016],{},[1397,4014,4015],{},"Yes: Use cached copy. No body transferred. Very fast.",[1397,4017,4018],{},"No: Download fresh copy. Normal response.",[341,4020,4022],{"id":4021},"cache-busting","Cache Busting",[16,4024,4025],{},"CSS and JavaScript files are often given fingerprinted filenames to force browsers to download new versions when code changes:",[44,4027,4029],{"className":3119,"code":4028,"language":3121,"meta":49,"style":49},"\u003C!-- Without cache busting: browser might serve stale CSS -->\n\u003Clink rel=\"stylesheet\" href=\"/styles.css\">\n\n\u003C!-- With cache busting: new hash = new file = fresh download -->\n\u003Clink rel=\"stylesheet\" href=\"/styles.a3f9b2.css\">\n",[20,4030,4031,4036,4061,4065,4070],{"__ignoreMap":49},[53,4032,4033],{"class":55,"line":56},[53,4034,4035],{"class":709},"\u003C!-- Without cache busting: browser might serve stale CSS -->\n",[53,4037,4038,4040,4043,4046,4048,4051,4054,4056,4059],{"class":55,"line":62},[53,4039,3143],{"class":2051},[53,4041,4042],{"class":3131},"link",[53,4044,4045],{"class":715}," rel",[53,4047,3473],{"class":2051},[53,4049,4050],{"class":719},"\"stylesheet\"",[53,4052,4053],{"class":715}," href",[53,4055,3473],{"class":2051},[53,4057,4058],{"class":719},"\"/styles.css\"",[53,4060,3138],{"class":2051},[53,4062,4063],{"class":55,"line":69},[53,4064,66],{"emptyLinePlaceholder":65},[53,4066,4067],{"class":55,"line":75},[53,4068,4069],{"class":709},"\u003C!-- With cache busting: new hash = new file = fresh download -->\n",[53,4071,4072,4074,4076,4078,4080,4082,4084,4086,4089],{"class":55,"line":81},[53,4073,3143],{"class":2051},[53,4075,4042],{"class":3131},[53,4077,4045],{"class":715},[53,4079,3473],{"class":2051},[53,4081,4050],{"class":719},[53,4083,4053],{"class":715},[53,4085,3473],{"class":2051},[53,4087,4088],{"class":719},"\"/styles.a3f9b2.css\"",[53,4090,3138],{"class":2051},[16,4092,4093,4094,4097],{},"Build tools like Vite, Webpack, and esbuild do this automatically. The CSS file itself can have ",[20,4095,4096],{},"Cache-Control: public, max-age=31536000, immutable"," (cache for 1 year) because the filename changes whenever the content changes.",[34,4099],{},[11,4101,4103],{"id":4102},"putting-it-all-together-the-full-timeline","Putting It All Together: The Full Timeline",[16,4105,4106],{},"Here is the complete journey one more time, annotated with timing characteristics for a realistic page load:",[44,4108,4110],{"className":46,"code":4109,"language":48,"meta":49,"style":49},"t=0ms\n  User presses Enter\n\nt=1ms\n  Browser checks cache for DNS record\n  (cache hit: skip to t=3ms)\n  (cache miss: DNS query begins)\n\nt=50ms  [DNS lookup]\n  Recursive resolver queries root, TLD, authoritative NS\n  Returns: 93.184.216.34\n\nt=51ms  [TCP handshake begins]\n  SYN sent to 93.184.216.34:443\n\nt=100ms [TCP + TLS handshake complete]\n  SYN-ACK received, ACK sent\n  TLS ClientHello/ServerHello exchanged\n  Encryption keys derived\n\nt=101ms [HTTP request sent]\n  GET /blog/article?id=42 HTTP/2\n\nt=150ms [HTTP response headers received]\n  200 OK, Content-Type: text/html\n\nt=180ms [HTML body fully received]\n  Browser begins parsing HTML\n\nt=185ms [CSS files discovered in \u003Chead>]\n  Browser sends parallel requests for CSS files\n\nt=220ms [CSS fully downloaded and parsed]\n  CSSOM built\n\nt=225ms [Render tree built]\n  DOM + CSSOM merged\n\nt=226ms [Layout calculated]\n\nt=228ms [First Contentful Paint (FCP)]\n  User sees something on screen!\n\nt=250ms [JavaScript files downloaded and executed]\n\nt=400ms [All images and fonts loaded]\n\nt=401ms [Page fully interactive]\n  All event listeners attached\n",[20,4111,4112,4117,4122,4126,4131,4136,4141,4146,4150,4155,4160,4165,4169,4174,4179,4183,4188,4193,4198,4203,4207,4212,4217,4221,4226,4231,4235,4240,4245,4249,4254,4259,4263,4268,4273,4277,4283,4289,4294,4300,4305,4311,4317,4322,4328,4333,4339,4344,4350],{"__ignoreMap":49},[53,4113,4114],{"class":55,"line":56},[53,4115,4116],{},"t=0ms\n",[53,4118,4119],{"class":55,"line":62},[53,4120,4121],{},"  User presses Enter\n",[53,4123,4124],{"class":55,"line":69},[53,4125,66],{"emptyLinePlaceholder":65},[53,4127,4128],{"class":55,"line":75},[53,4129,4130],{},"t=1ms\n",[53,4132,4133],{"class":55,"line":81},[53,4134,4135],{},"  Browser checks cache for DNS record\n",[53,4137,4138],{"class":55,"line":87},[53,4139,4140],{},"  (cache hit: skip to t=3ms)\n",[53,4142,4143],{"class":55,"line":93},[53,4144,4145],{},"  (cache miss: DNS query begins)\n",[53,4147,4148],{"class":55,"line":99},[53,4149,66],{"emptyLinePlaceholder":65},[53,4151,4152],{"class":55,"line":105},[53,4153,4154],{},"t=50ms  [DNS lookup]\n",[53,4156,4157],{"class":55,"line":111},[53,4158,4159],{},"  Recursive resolver queries root, TLD, authoritative NS\n",[53,4161,4162],{"class":55,"line":117},[53,4163,4164],{},"  Returns: 93.184.216.34\n",[53,4166,4167],{"class":55,"line":123},[53,4168,66],{"emptyLinePlaceholder":65},[53,4170,4171],{"class":55,"line":129},[53,4172,4173],{},"t=51ms  [TCP handshake begins]\n",[53,4175,4176],{"class":55,"line":135},[53,4177,4178],{},"  SYN sent to 93.184.216.34:443\n",[53,4180,4181],{"class":55,"line":141},[53,4182,66],{"emptyLinePlaceholder":65},[53,4184,4185],{"class":55,"line":147},[53,4186,4187],{},"t=100ms [TCP + TLS handshake complete]\n",[53,4189,4190],{"class":55,"line":439},[53,4191,4192],{},"  SYN-ACK received, ACK sent\n",[53,4194,4195],{"class":55,"line":445},[53,4196,4197],{},"  TLS ClientHello/ServerHello exchanged\n",[53,4199,4200],{"class":55,"line":451},[53,4201,4202],{},"  Encryption keys derived\n",[53,4204,4205],{"class":55,"line":457},[53,4206,66],{"emptyLinePlaceholder":65},[53,4208,4209],{"class":55,"line":462},[53,4210,4211],{},"t=101ms [HTTP request sent]\n",[53,4213,4214],{"class":55,"line":468},[53,4215,4216],{},"  GET /blog/article?id=42 HTTP/2\n",[53,4218,4219],{"class":55,"line":473},[53,4220,66],{"emptyLinePlaceholder":65},[53,4222,4223],{"class":55,"line":479},[53,4224,4225],{},"t=150ms [HTTP response headers received]\n",[53,4227,4228],{"class":55,"line":484},[53,4229,4230],{},"  200 OK, Content-Type: text/html\n",[53,4232,4233],{"class":55,"line":490},[53,4234,66],{"emptyLinePlaceholder":65},[53,4236,4237],{"class":55,"line":495},[53,4238,4239],{},"t=180ms [HTML body fully received]\n",[53,4241,4242],{"class":55,"line":501},[53,4243,4244],{},"  Browser begins parsing HTML\n",[53,4246,4247],{"class":55,"line":506},[53,4248,66],{"emptyLinePlaceholder":65},[53,4250,4251],{"class":55,"line":2345},[53,4252,4253],{},"t=185ms [CSS files discovered in \u003Chead>]\n",[53,4255,4256],{"class":55,"line":2351},[53,4257,4258],{},"  Browser sends parallel requests for CSS files\n",[53,4260,4261],{"class":55,"line":2366},[53,4262,66],{"emptyLinePlaceholder":65},[53,4264,4265],{"class":55,"line":3092},[53,4266,4267],{},"t=220ms [CSS fully downloaded and parsed]\n",[53,4269,4270],{"class":55,"line":3097},[53,4271,4272],{},"  CSSOM built\n",[53,4274,4275],{"class":55,"line":3102},[53,4276,66],{"emptyLinePlaceholder":65},[53,4278,4280],{"class":55,"line":4279},36,[53,4281,4282],{},"t=225ms [Render tree built]\n",[53,4284,4286],{"class":55,"line":4285},37,[53,4287,4288],{},"  DOM + CSSOM merged\n",[53,4290,4292],{"class":55,"line":4291},38,[53,4293,66],{"emptyLinePlaceholder":65},[53,4295,4297],{"class":55,"line":4296},39,[53,4298,4299],{},"t=226ms [Layout calculated]\n",[53,4301,4303],{"class":55,"line":4302},40,[53,4304,66],{"emptyLinePlaceholder":65},[53,4306,4308],{"class":55,"line":4307},41,[53,4309,4310],{},"t=228ms [First Contentful Paint (FCP)]\n",[53,4312,4314],{"class":55,"line":4313},42,[53,4315,4316],{},"  User sees something on screen!\n",[53,4318,4320],{"class":55,"line":4319},43,[53,4321,66],{"emptyLinePlaceholder":65},[53,4323,4325],{"class":55,"line":4324},44,[53,4326,4327],{},"t=250ms [JavaScript files downloaded and executed]\n",[53,4329,4331],{"class":55,"line":4330},45,[53,4332,66],{"emptyLinePlaceholder":65},[53,4334,4336],{"class":55,"line":4335},46,[53,4337,4338],{},"t=400ms [All images and fonts loaded]\n",[53,4340,4342],{"class":55,"line":4341},47,[53,4343,66],{"emptyLinePlaceholder":65},[53,4345,4347],{"class":55,"line":4346},48,[53,4348,4349],{},"t=401ms [Page fully interactive]\n",[53,4351,4353],{"class":55,"line":4352},49,[53,4354,4355],{},"  All event listeners attached\n",[16,4357,4358],{},"The specific times vary enormously based on network speed, server location, file sizes, and server performance. The sequence, however, is always the same.",[34,4360],{},[11,4362,4364],{"id":4363},"common-performance-metrics-and-what-they-measure","Common Performance Metrics and What They Measure",[16,4366,4367],{},"When developers talk about web performance, they use specific metrics that correspond to points in the rendering timeline:",[184,4369,4370,4383],{},[187,4371,4372],{},[190,4373,4374,4377,4380],{},[193,4375,4376],{},"Metric",[193,4378,4379],{},"What it measures",[193,4381,4382],{},"Good threshold",[203,4384,4385,4396,4407,4418,4429,4440],{},[190,4386,4387,4390,4393],{},[208,4388,4389],{},"TTFB (Time to First Byte)",[208,4391,4392],{},"When did the first byte of the HTML response arrive?",[208,4394,4395],{},"\u003C 800ms",[190,4397,4398,4401,4404],{},[208,4399,4400],{},"FCP (First Contentful Paint)",[208,4402,4403],{},"When did the user see any content?",[208,4405,4406],{},"\u003C 1.8s",[190,4408,4409,4412,4415],{},[208,4410,4411],{},"LCP (Largest Contentful Paint)",[208,4413,4414],{},"When did the main content appear?",[208,4416,4417],{},"\u003C 2.5s",[190,4419,4420,4423,4426],{},[208,4421,4422],{},"TBT (Total Blocking Time)",[208,4424,4425],{},"How long was the main thread blocked by JS?",[208,4427,4428],{},"\u003C 200ms",[190,4430,4431,4434,4437],{},[208,4432,4433],{},"CLS (Cumulative Layout Shift)",[208,4435,4436],{},"How much did content jump around during load?",[208,4438,4439],{},"\u003C 0.1",[190,4441,4442,4445,4448],{},[208,4443,4444],{},"TTI (Time to Interactive)",[208,4446,4447],{},"When could the user interact with the page?",[208,4449,4450],{},"\u003C 3.8s",[16,4452,4453],{},"Google uses Core Web Vitals (LCP, TBT, CLS) as a ranking signal in search results. Performance is not just a user experience concern; it affects SEO directly.",[34,4455],{},[11,4457,4459],{"id":4458},"security-considerations-at-each-layer","Security Considerations at Each Layer",[16,4461,4462],{},"The web's architecture introduces potential attack surfaces at every layer. Here is a brief map:",[184,4464,4465,4478],{},[187,4466,4467],{},[190,4468,4469,4472,4475],{},[193,4470,4471],{},"Layer",[193,4473,4474],{},"Common Attack",[193,4476,4477],{},"Defense",[203,4479,4480,4491,4502,4513,4524],{},[190,4481,4482,4485,4488],{},[208,4483,4484],{},"DNS",[208,4486,4487],{},"DNS spoofing, cache poisoning",[208,4489,4490],{},"DNSSEC, use trusted resolvers",[190,4492,4493,4496,4499],{},[208,4494,4495],{},"Transport",[208,4497,4498],{},"Man-in-the-middle attacks",[208,4500,4501],{},"TLS, HSTS, certificate pinning",[190,4503,4504,4507,4510],{},[208,4505,4506],{},"HTTP",[208,4508,4509],{},"Cookie theft, session hijacking",[208,4511,4512],{},"HttpOnly/Secure cookies, SameSite",[190,4514,4515,4518,4521],{},[208,4516,4517],{},"Application",[208,4519,4520],{},"SQL injection, XSS, CSRF",[208,4522,4523],{},"Parameterized queries, CSP, CSRF tokens",[190,4525,4526,4529,4532],{},[208,4527,4528],{},"Caching",[208,4530,4531],{},"Serving stale/wrong content to wrong user",[208,4533,4534,4537],{},[20,4535,4536],{},"Cache-Control: private"," for user data",[16,4539,4540,4541,4544],{},"The ",[20,4542,4543],{},"Content-Security-Policy"," (CSP) header is worth highlighting. It tells the browser which sources of scripts, styles, and images are allowed:",[44,4546,4548],{"className":46,"code":4547,"language":48,"meta":49,"style":49},"Content-Security-Policy: default-src 'self';\n  script-src 'self' https://cdn.example.com;\n  img-src 'self' data: https:;\n  style-src 'self' 'unsafe-inline';\n",[20,4549,4550,4555,4560,4565],{"__ignoreMap":49},[53,4551,4552],{"class":55,"line":56},[53,4553,4554],{},"Content-Security-Policy: default-src 'self';\n",[53,4556,4557],{"class":55,"line":62},[53,4558,4559],{},"  script-src 'self' https://cdn.example.com;\n",[53,4561,4562],{"class":55,"line":69},[53,4563,4564],{},"  img-src 'self' data: https:;\n",[53,4566,4567],{"class":55,"line":75},[53,4568,4569],{},"  style-src 'self' 'unsafe-inline';\n",[16,4571,4572],{},"This prevents XSS attacks from injecting and executing malicious scripts, even if an attacker manages to inject HTML into your page.",[34,4574],{},[11,4576,4578],{"id":4577},"summary-the-30-second-version","Summary: The 30-Second Version",[16,4580,4581],{},"Here is the entire web request lifecycle condensed:",[2525,4583,4584,4590,4596,4602,4608,4614,4620,4626,4632,4638],{},[1397,4585,4586,4589],{},[516,4587,4588],{},"URL parsing:"," Browser breaks the URL into scheme, host, port, path, query",[1397,4591,4592,4595],{},[516,4593,4594],{},"DNS:"," Domain name translated to an IP address through a hierarchy of servers",[1397,4597,4598,4601],{},[516,4599,4600],{},"TCP handshake:"," 3-packet exchange establishes a reliable connection",[1397,4603,4604,4607],{},[516,4605,4606],{},"TLS handshake:"," Encryption keys negotiated, server identity verified (HTTPS only)",[1397,4609,4610,4613],{},[516,4611,4612],{},"HTTP request:"," Browser sends a structured message asking for the resource",[1397,4615,4616,4619],{},[516,4617,4618],{},"Server processing:"," Web server, app server, and database work together to generate a response",[1397,4621,4622,4625],{},[516,4623,4624],{},"HTTP response:"," Server sends status code, headers, and the resource body",[1397,4627,4628,4631],{},[516,4629,4630],{},"Browser rendering:"," Browser parses HTML into DOM, CSS into CSSOM, builds Render Tree, calculates Layout, Paints pixels",[1397,4633,4634,4637],{},[516,4635,4636],{},"Sub-resources:"," Browser fetches CSS, JS, images, fonts referenced in the HTML",[1397,4639,4640,4643],{},[516,4641,4642],{},"Interactivity:"," JavaScript executes, event listeners attach, page becomes interactive",[16,4645,4646],{},"Every single time you visit a webpage, this entire sequence runs, often in under a second. The fact that it works reliably at the scale of billions of requests per second, across unreliable networks, heterogeneous hardware, and wildly different software stacks, is one of the genuine engineering achievements of our time.",[34,4648],{},[11,4650,4652],{"id":4651},"what-to-learn-next","What to Learn Next",[16,4654,4655],{},"If this post sparked your curiosity, here are natural next topics to explore:",[1394,4657,4658,4664,4670,4676,4682,4688,4704],{},[1397,4659,4660,4663],{},[516,4661,4662],{},"HTTP/2 and HTTP/3 in depth:"," multiplexing, server push, QUIC protocol",[1397,4665,4666,4669],{},[516,4667,4668],{},"TLS 1.3:"," how the modern handshake is faster and more secure than TLS 1.2",[1397,4671,4672,4675],{},[516,4673,4674],{},"Service Workers:"," JavaScript that intercepts network requests and enables offline web apps",[1397,4677,4678,4681],{},[516,4679,4680],{},"CDNs:"," how content delivery networks distribute your content globally and reduce latency",[1397,4683,4684,4687],{},[516,4685,4686],{},"DNS security (DNSSEC):"," cryptographic verification of DNS responses",[1397,4689,4690,4693,4694,523,4697,523,4700,4703],{},[516,4691,4692],{},"Web performance optimization:"," Core Web Vitals, resource hints (",[20,4695,4696],{},"preload",[20,4698,4699],{},"prefetch",[20,4701,4702],{},"preconnect","), image optimization",[1397,4705,4706,1389,4709,523,4712,4715],{},[516,4707,4708],{},"HTTP caching strategies:",[20,4710,4711],{},"stale-while-revalidate",[20,4713,4714],{},"immutable",", cache hierarchies",[16,4717,4718],{},"The web is a deep rabbit hole. The further you go, the more elegant the design becomes.",[16,4720,4721],{},"Thanks for reading!",[4723,4724,4725],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}",{"title":49,"searchDepth":62,"depth":62,"links":4727},[4728,4729,4730,4731,4738,4743,4748,4754,4760,4765,4774,4778,4783,4784,4785,4786,4787],{"id":13,"depth":62,"text":14},{"id":38,"depth":62,"text":39},{"id":158,"depth":62,"text":159},{"id":328,"depth":62,"text":329,"children":4732},[4733,4734,4735,4736,4737],{"id":343,"depth":69,"text":344},{"id":350,"depth":69,"text":351},{"id":564,"depth":69,"text":565},{"id":693,"depth":69,"text":694},{"id":815,"depth":69,"text":816},{"id":855,"depth":62,"text":856,"children":4739},[4740,4741,4742],{"id":869,"depth":69,"text":870},{"id":954,"depth":69,"text":955},{"id":1024,"depth":69,"text":1025},{"id":1036,"depth":62,"text":1037,"children":4744},[4745,4746,4747],{"id":1055,"depth":69,"text":1056},{"id":1201,"depth":69,"text":1202},{"id":1256,"depth":69,"text":1257},{"id":1314,"depth":62,"text":1315,"children":4749},[4750,4751,4752,4753],{"id":1324,"depth":69,"text":1325},{"id":1469,"depth":69,"text":1470},{"id":1626,"depth":69,"text":1627},{"id":1677,"depth":69,"text":1678},{"id":1746,"depth":62,"text":1747,"children":4755},[4756,4757,4758,4759],{"id":1756,"depth":69,"text":1757},{"id":1900,"depth":69,"text":1901},{"id":2013,"depth":69,"text":2014},{"id":2374,"depth":69,"text":2375},{"id":2550,"depth":62,"text":2551,"children":4761},[4762,4763,4764],{"id":2557,"depth":69,"text":2558},{"id":2640,"depth":69,"text":2641},{"id":2790,"depth":69,"text":2791},{"id":2924,"depth":62,"text":2925,"children":4766},[4767,4768,4769,4770,4771,4772,4773],{"id":2935,"depth":69,"text":2936},{"id":3108,"depth":69,"text":3109},{"id":3293,"depth":69,"text":3294},{"id":3435,"depth":69,"text":3436},{"id":3564,"depth":69,"text":3565},{"id":3593,"depth":69,"text":3594},{"id":3624,"depth":69,"text":3625},{"id":3699,"depth":62,"text":3700,"children":4775},[4776,4777],{"id":3706,"depth":69,"text":3707},{"id":3830,"depth":69,"text":3831},{"id":3866,"depth":62,"text":3867,"children":4779},[4780,4781,4782],{"id":3873,"depth":69,"text":3874},{"id":3972,"depth":69,"text":3973},{"id":4021,"depth":69,"text":4022},{"id":4102,"depth":62,"text":4103},{"id":4363,"depth":62,"text":4364},{"id":4458,"depth":62,"text":4459},{"id":4577,"depth":62,"text":4578},{"id":4651,"depth":62,"text":4652},"Web Fundamentals","/blog-covers/how-the-web-works.png","2026-04-27","A deep technical walkthrough of what happens between typing a URL and seeing a webpage, covering DNS, TCP/IP, TLS, HTTP, servers, and browser rendering with diagrams and code examples.","md",{},"/posts/how-the-web-works","30 min read",{"title":5,"description":4791},{"loc":4794,"lastmod":4790},"posts/how-the-web-works",[4800,1333,4801,4802,4803,4804,4805,4806,215],"web","dns","tcp-ip","browser","server","networking","tls","z9VggsdjZNcaw-RA7TdXWt8DmRrK0_U5okoGL1lWuhw",1777897734631]