[{"data":1,"prerenderedAt":7917},["ShallowReactive",2],{"blog-article:en:frontend-observability":3,"blog-translations:frontend-observability":1119,"related-blog-articles:en:frontend-observability":1127},{"id":4,"title":5,"author":6,"body":7,"category":1104,"description":1105,"draft":1106,"extension":1107,"featured":280,"image":1108,"imageAlt":1109,"locale":1110,"meta":1111,"navigation":280,"path":1112,"publishedAt":1113,"readingTime":265,"seo":1114,"slug":1115,"stem":1116,"translationKey":1115,"updatedAt":1113,"wordCount":1117,"__hash__":1118},"blog\u002Fblog\u002Fen\u002Ffrontend-observability.md","Frontend Observability: Errors, Web Vitals, Network & Sessions","SeoNest Team",{"type":8,"value":9,"toc":1089},"minimark",[10,15,24,35,38,42,53,60,64,131,134,141,145,148,164,167,348,351,363,368,372,375,378,400,424,427,438,538,548,553,557,560,572,583,736,745,755,762,766,772,779,782,790,793,796,804,811,815,818,821,824,850,853,856,860,866,872,878,884,890,896,900,903,906,909,916,920,925,928,932,935,939,942,946,949,953,956,974,977,981,1085],[11,12,14],"h2",{"id":13},"frontend-observability-errors-web-vitals-network-and-sessions","Frontend Observability: Errors, Web Vitals, Network, and Sessions",[16,17,18,19,23],"p",{},"A page can return ",[20,21,22],"code",{},"200 OK"," while a real user sees a broken checkout button, a four-second content load, a failed API request, or a layout that jumps just before they click. Server monitoring alone cannot see all of this because much of the application now executes inside the browser.",[16,25,26,27,31,32],{},"Frontend observability fills that gap. It collects evidence from real browser sessions so engineers can answer not only ",[28,29,30],"strong",{},"“Is the site running?”"," but also ",[28,33,34],{},"“What did this user experience, and why?”",[16,36,37],{},"The most useful frontend observability systems connect four kinds of evidence: JavaScript errors, Web Vitals, network activity, and session context.",[11,39,41],{"id":40},"direct-answer","Direct Answer",[16,43,44,45,52],{},"Frontend observability is the practice of instrumenting a website or web application so its real behavior inside users' browsers can be understood from telemetry. Observability generally relies on outputs such as logs, metrics, and traces; on the frontend, this expands naturally into browser errors, user-experience metrics, resource timing, route changes, and session-level context. (",[46,47,51],"a",{"href":48,"rel":49},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fwhat-is-opentelemetry\u002F?utm_source=chatgpt.com",[50],"nofollow","opentelemetry.io",")",[16,54,55,56,59],{},"The goal is not to collect everything. The goal is to connect enough evidence to move from ",[28,57,58],{},"symptom → affected session → technical cause → verified fix",".",[11,61,63],{"id":62},"four-signals-that-matter","Four Signals That Matter",[65,66,67,83],"table",{},[68,69,70],"thead",{},[71,72,73,77,80],"tr",{},[74,75,76],"th",{},"Signal",[74,78,79],{},"Main question",[74,81,82],{},"Typical evidence",[84,85,86,98,109,120],"tbody",{},[71,87,88,92,95],{},[89,90,91],"td",{},"Errors",[89,93,94],{},"What broke?",[89,96,97],{},"Exception, stack trace, route, release",[71,99,100,103,106],{},[89,101,102],{},"Web Vitals",[89,104,105],{},"What felt slow or unstable?",[89,107,108],{},"LCP, INP, CLS",[71,110,111,114,117],{},[89,112,113],{},"Network",[89,115,116],{},"Which request or resource caused delay?",[89,118,119],{},"DNS, connection, request, response timing",[71,121,122,125,128],{},[89,123,124],{},"Sessions",[89,126,127],{},"What happened around the problem?",[89,129,130],{},"Route, actions, errors, requests, optional replay",[16,132,133],{},"Individually, each signal is useful. Together, they become far more diagnostic.",[16,135,136,137,140],{},"An INP value of ",[28,138,139],{},"620 ms"," tells you that an interaction was slow. An error says a function failed. A request lasting three seconds says the network path was expensive. But if all three belong to the same session and interaction, the investigation becomes much more precise.",[11,142,144],{"id":143},"error-visibility","Error Visibility",[16,146,147],{},"Browser consoles are useful during development, but production failures happen on devices you do not control. Frontend error monitoring therefore starts by capturing failures and attaching useful context.",[16,149,150,151,154,155,158,159,52],{},"Browsers expose an ",[20,152,153],{},"error"," event for synchronous script failures and an ",[20,156,157],{},"unhandledrejection"," event when a Promise is rejected without a rejection handler. MDN also notes that cross-origin restrictions can limit some unhandled-rejection reporting. (",[46,160,163],{"href":161,"rel":162},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWindow\u002Ferror_event?utm_source=chatgpt.com",[50],"developer.mozilla.org",[16,165,166],{},"A minimal implementation might look like this:",[168,169,174],"pre",{"className":170,"code":171,"language":172,"meta":173,"style":173},"language-js shiki shiki-themes github-light github-dark","window.addEventListener('error', (event) => {\n    reportError({\n        type: 'error',\n        message: event.message,\n        file: event.filename,\n        line: event.lineno,\n        column: event.colno,\n        stack: event.error?.stack,\n    });\n});\n\nwindow.addEventListener('unhandledrejection', (event) => {\n    reportError({\n        type: 'unhandledrejection',\n        message: String(event.reason),\n        stack: event.reason?.stack,\n    });\n});\n","js","",[20,175,176,213,222,233,239,245,251,257,263,269,275,282,304,311,320,332,338,343],{"__ignoreMap":173},[177,178,181,185,189,192,196,199,203,206,210],"span",{"class":179,"line":180},"line",1,[177,182,184],{"class":183},"sVt8B","window.",[177,186,188],{"class":187},"sScJk","addEventListener",[177,190,191],{"class":183},"(",[177,193,195],{"class":194},"sZZnC","'error'",[177,197,198],{"class":183},", (",[177,200,202],{"class":201},"s4XuR","event",[177,204,205],{"class":183},") ",[177,207,209],{"class":208},"szBVR","=>",[177,211,212],{"class":183}," {\n",[177,214,216,219],{"class":179,"line":215},2,[177,217,218],{"class":187},"    reportError",[177,220,221],{"class":183},"({\n",[177,223,225,228,230],{"class":179,"line":224},3,[177,226,227],{"class":183},"        type: ",[177,229,195],{"class":194},[177,231,232],{"class":183},",\n",[177,234,236],{"class":179,"line":235},4,[177,237,238],{"class":183},"        message: event.message,\n",[177,240,242],{"class":179,"line":241},5,[177,243,244],{"class":183},"        file: event.filename,\n",[177,246,248],{"class":179,"line":247},6,[177,249,250],{"class":183},"        line: event.lineno,\n",[177,252,254],{"class":179,"line":253},7,[177,255,256],{"class":183},"        column: event.colno,\n",[177,258,260],{"class":179,"line":259},8,[177,261,262],{"class":183},"        stack: event.error?.stack,\n",[177,264,266],{"class":179,"line":265},9,[177,267,268],{"class":183},"    });\n",[177,270,272],{"class":179,"line":271},10,[177,273,274],{"class":183},"});\n",[177,276,278],{"class":179,"line":277},11,[177,279,281],{"emptyLinePlaceholder":280},true,"\n",[177,283,285,287,289,291,294,296,298,300,302],{"class":179,"line":284},12,[177,286,184],{"class":183},[177,288,188],{"class":187},[177,290,191],{"class":183},[177,292,293],{"class":194},"'unhandledrejection'",[177,295,198],{"class":183},[177,297,202],{"class":201},[177,299,205],{"class":183},[177,301,209],{"class":208},[177,303,212],{"class":183},[177,305,307,309],{"class":179,"line":306},13,[177,308,218],{"class":187},[177,310,221],{"class":183},[177,312,314,316,318],{"class":179,"line":313},14,[177,315,227],{"class":183},[177,317,293],{"class":194},[177,319,232],{"class":183},[177,321,323,326,329],{"class":179,"line":322},15,[177,324,325],{"class":183},"        message: ",[177,327,328],{"class":187},"String",[177,330,331],{"class":183},"(event.reason),\n",[177,333,335],{"class":179,"line":334},16,[177,336,337],{"class":183},"        stack: event.reason?.stack,\n",[177,339,341],{"class":179,"line":340},17,[177,342,268],{"class":183},[177,344,346],{"class":179,"line":345},18,[177,347,274],{"class":183},[16,349,350],{},"In production, the error itself is only the beginning. Useful records normally include the application release, route, browser, environment and a session identifier. Errors should also be grouped so one defect affecting 50,000 users does not appear as 50,000 unrelated incidents.",[16,352,353,354,357,358,52],{},"Minified production bundles introduce another problem: a stack trace may point to something like ",[20,355,356],{},"app.8f72d.js:1:48217",". Source maps map generated code back to original JavaScript, WebAssembly, or CSS sources. Their format is standardized by ECMA-426, whose first edition was published in December 2024. (",[46,359,362],{"href":360,"rel":361},"https:\u002F\u002Fecma-international.org\u002Fpublications-and-standards\u002Fstandards\u002Fecma-426\u002F?utm_source=chatgpt.com",[50],"ecma-international.org",[16,364,365],{},[177,366,367],{},"INTERNAL LINK: JavaScript Source Maps Explained",[11,369,371],{"id":370},"real-user-web-vitals","Real-User Web Vitals",[16,373,374],{},"Errors tell you when software fails. Performance telemetry tells you when software technically works but delivers a poor experience.",[16,376,377],{},"The current Core Web Vitals are:",[379,380,381,388,394],"ul",{},[382,383,384,387],"li",{},[28,385,386],{},"Largest Contentful Paint (LCP):"," loading performance.",[382,389,390,393],{},[28,391,392],{},"Interaction to Next Paint (INP):"," responsiveness.",[382,395,396,399],{},[28,397,398],{},"Cumulative Layout Shift (CLS):"," visual stability.",[16,401,402,403,406,407,410,411,414,415,418,419,52],{},"Google's documented “good” thresholds are ",[28,404,405],{},"LCP ≤ 2.5 seconds",", ",[28,408,409],{},"INP ≤ 200 milliseconds",", and ",[28,412,413],{},"CLS ≤ 0.1",". These should be evaluated at the ",[28,416,417],{},"75th percentile"," of page visits, with mobile and desktop considered separately. (",[46,420,423],{"href":421,"rel":422},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fvitals?authuser=01&utm_source=chatgpt.com",[50],"web.dev",[16,425,426],{},"That percentile matters. An average can make a site look healthy while a meaningful portion of users consistently receive a poor experience.",[16,428,429,430,433,434,52],{},"For production monitoring, Google's ",[20,431,432],{},"web-vitals"," library provides an easier way to collect measurements consistent with the Web Vitals methodology. Google also provides an attribution build that adds diagnostic context for investigating poor measurements. (",[46,435,423],{"href":436,"rel":437},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fvitals-measurement-getting-started?utm_source=chatgpt.com",[50],[168,439,441],{"className":170,"code":440,"language":172,"meta":173,"style":173},"import { onCLS, onINP, onLCP } from 'web-vitals\u002Fattribution';\n\nfunction report(metric) {\n    navigator.sendBeacon('\u002Frum', JSON.stringify(metric));\n}\n\nonLCP(report);\nonINP(report);\nonCLS(report);\n",[20,442,443,460,464,480,507,512,516,524,531],{"__ignoreMap":173},[177,444,445,448,451,454,457],{"class":179,"line":180},[177,446,447],{"class":208},"import",[177,449,450],{"class":183}," { onCLS, onINP, onLCP } ",[177,452,453],{"class":208},"from",[177,455,456],{"class":194}," 'web-vitals\u002Fattribution'",[177,458,459],{"class":183},";\n",[177,461,462],{"class":179,"line":215},[177,463,281],{"emptyLinePlaceholder":280},[177,465,466,469,472,474,477],{"class":179,"line":224},[177,467,468],{"class":208},"function",[177,470,471],{"class":187}," report",[177,473,191],{"class":183},[177,475,476],{"class":201},"metric",[177,478,479],{"class":183},") {\n",[177,481,482,485,488,490,493,495,499,501,504],{"class":179,"line":235},[177,483,484],{"class":183},"    navigator.",[177,486,487],{"class":187},"sendBeacon",[177,489,191],{"class":183},[177,491,492],{"class":194},"'\u002Frum'",[177,494,406],{"class":183},[177,496,498],{"class":497},"sj4cs","JSON",[177,500,59],{"class":183},[177,502,503],{"class":187},"stringify",[177,505,506],{"class":183},"(metric));\n",[177,508,509],{"class":179,"line":241},[177,510,511],{"class":183},"}\n",[177,513,514],{"class":179,"line":247},[177,515,281],{"emptyLinePlaceholder":280},[177,517,518,521],{"class":179,"line":253},[177,519,520],{"class":187},"onLCP",[177,522,523],{"class":183},"(report);\n",[177,525,526,529],{"class":179,"line":259},[177,527,528],{"class":187},"onINP",[177,530,523],{"class":183},[177,532,533,536],{"class":179,"line":265},[177,534,535],{"class":187},"onCLS",[177,537,523],{"class":183},[16,539,540,541,544,545,52],{},"The important distinction is ",[28,542,543],{},"field versus lab data",". Lighthouse and local profiling help reproduce and investigate problems under controlled conditions. Real User Monitoring, or RUM, shows what actually happened across real devices, networks and sessions. Google explicitly recommends using field measurements when assessing real-user Web Vitals. (",[46,546,423],{"href":436,"rel":547},[50],[16,549,550],{},[177,551,552],{},"INTERNAL LINK: Core Web Vitals Explained",[11,554,556],{"id":555},"network-observability","Network Observability",[16,558,559],{},"A slow frontend is not always a JavaScript problem. The browser may be waiting for DNS resolution, a connection, server processing, an image, a third-party script, or an API response.",[16,561,562,563,566,567,52],{},"The Resource Timing API exposes detailed resource-loading information. The current W3C Resource Timing draft defines ",[20,564,565],{},"PerformanceResourceTiming",", including timestamps and metadata around fetching page resources. (",[46,568,571],{"href":569,"rel":570},"https:\u002F\u002Fwww.w3.org\u002FTR\u002Fresource-timing\u002F?utm_source=chatgpt.com",[50],"w3.org",[16,573,574,575,578,579,52],{},"Browsers expose these entries through the Performance Timeline and ",[20,576,577],{},"PerformanceObserver",". (",[46,580,571],{"href":581,"rel":582},"https:\u002F\u002Fwww.w3.org\u002FTR\u002Fperformance-timeline\u002F?utm_source=chatgpt.com",[50],[168,584,586],{"className":170,"code":585,"language":172,"meta":173,"style":173},"const observer = new PerformanceObserver((list) => {\n    for (const entry of list.getEntries()) {\n        reportNetwork({\n            url: entry.name,\n            type: entry.initiatorType,\n            duration: entry.duration,\n            requestStart: entry.requestStart,\n            responseStart: entry.responseStart,\n            responseEnd: entry.responseEnd,\n            transferSize: entry.transferSize,\n        });\n    }\n});\n\nobserver.observe({\n    type: 'resource',\n    buffered: true,\n});\n",[20,587,588,617,642,649,654,659,664,669,674,679,684,689,694,698,702,712,722,732],{"__ignoreMap":173},[177,589,590,593,596,599,602,605,608,611,613,615],{"class":179,"line":180},[177,591,592],{"class":208},"const",[177,594,595],{"class":497}," observer",[177,597,598],{"class":208}," =",[177,600,601],{"class":208}," new",[177,603,604],{"class":187}," PerformanceObserver",[177,606,607],{"class":183},"((",[177,609,610],{"class":201},"list",[177,612,205],{"class":183},[177,614,209],{"class":208},[177,616,212],{"class":183},[177,618,619,622,625,627,630,633,636,639],{"class":179,"line":215},[177,620,621],{"class":208},"    for",[177,623,624],{"class":183}," (",[177,626,592],{"class":208},[177,628,629],{"class":497}," entry",[177,631,632],{"class":208}," of",[177,634,635],{"class":183}," list.",[177,637,638],{"class":187},"getEntries",[177,640,641],{"class":183},"()) {\n",[177,643,644,647],{"class":179,"line":224},[177,645,646],{"class":187},"        reportNetwork",[177,648,221],{"class":183},[177,650,651],{"class":179,"line":235},[177,652,653],{"class":183},"            url: entry.name,\n",[177,655,656],{"class":179,"line":241},[177,657,658],{"class":183},"            type: entry.initiatorType,\n",[177,660,661],{"class":179,"line":247},[177,662,663],{"class":183},"            duration: entry.duration,\n",[177,665,666],{"class":179,"line":253},[177,667,668],{"class":183},"            requestStart: entry.requestStart,\n",[177,670,671],{"class":179,"line":259},[177,672,673],{"class":183},"            responseStart: entry.responseStart,\n",[177,675,676],{"class":179,"line":265},[177,677,678],{"class":183},"            responseEnd: entry.responseEnd,\n",[177,680,681],{"class":179,"line":271},[177,682,683],{"class":183},"            transferSize: entry.transferSize,\n",[177,685,686],{"class":179,"line":277},[177,687,688],{"class":183},"        });\n",[177,690,691],{"class":179,"line":284},[177,692,693],{"class":183},"    }\n",[177,695,696],{"class":179,"line":306},[177,697,274],{"class":183},[177,699,700],{"class":179,"line":313},[177,701,281],{"emptyLinePlaceholder":280},[177,703,704,707,710],{"class":179,"line":322},[177,705,706],{"class":183},"observer.",[177,708,709],{"class":187},"observe",[177,711,221],{"class":183},[177,713,714,717,720],{"class":179,"line":334},[177,715,716],{"class":183},"    type: ",[177,718,719],{"class":194},"'resource'",[177,721,232],{"class":183},[177,723,724,727,730],{"class":179,"line":340},[177,725,726],{"class":183},"    buffered: ",[177,728,729],{"class":497},"true",[177,731,232],{"class":183},[177,733,734],{"class":179,"line":345},[177,735,274],{"class":183},[16,737,738,740,741,52],{},[20,739,565],{}," can expose phases such as DNS lookup, connection setup, request start, response start and response end, making it possible to distinguish different classes of delay. (",[46,742,163],{"href":743,"rel":744},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FPerformanceResourceTiming?utm_source=chatgpt.com",[50],[16,746,747,748,751,752,52],{},"There is an important limitation: detailed timing for cross-origin resources is restricted by default. A third-party resource must explicitly expose timing information using the ",[20,749,750],{},"Timing-Allow-Origin"," response header. (",[46,753,571],{"href":569,"rel":754},[50],[16,756,757,758,761],{},"This prevents a common diagnostic mistake. Seeing that ",[20,759,760],{},"analytics.example.com\u002Fscript.js"," took two seconds does not automatically tell you whether two seconds came from DNS, connection establishment, server response time or downloading the body. Your available evidence depends on browser security rules and server configuration.",[11,763,765],{"id":764},"session-context","Session Context",[16,767,768,769],{},"The fourth signal answers a different question: ",[28,770,771],{},"what was happening when the problem occurred?",[16,773,774,775,778],{},"Consider an error called ",[20,776,777],{},"Cannot read properties of undefined",". Without context, an engineer may need to reproduce it manually.",[16,780,781],{},"Now attach:",[168,783,788],{"className":784,"code":786,"language":787,"meta":173},[785],"language-text","Release: 2026.09.25-4\nRoute: \u002Fcheckout\u002Fpayment\nSession: a8f2...\nPrevious action: Click \"Pay\"\nAPI: POST \u002Fpayments → 500\nINP: 684 ms\nError: PaymentForm.submit\n","text",[20,789,786],{"__ignoreMap":173},[16,791,792],{},"The incident now tells a story.",[16,794,795],{},"Session context does not necessarily mean recording every user action. Start with lightweight metadata: session ID, route, navigation sequence, release, relevant actions, errors, performance measurements and request correlation.",[16,797,798,799,52],{},"Session replay can provide additional visual context, but it introduces significant privacy responsibilities. Implementations are vendor-specific rather than a browser observability standard. For example, Datadog documents masking controls for Session Replay and notes that masked values can be prevented from leaving the user's device. (",[46,800,803],{"href":801,"rel":802},"https:\u002F\u002Fdocs.datadoghq.com\u002Fdata_security\u002F?utm_source=chatgpt.com",[50],"docs.datadoghq.com",[16,805,806,807,810],{},"The practical rule is simple: ",[28,808,809],{},"collect the minimum information required to diagnose the problem",". Mask form values and sensitive DOM content, avoid passwords and authentication tokens entirely, apply sampling, and define retention intentionally.",[11,812,814],{"id":813},"correlate-the-signals","Correlate the Signals",[16,816,817],{},"The largest improvement in frontend observability usually comes from correlation rather than collecting another metric.",[16,819,820],{},"Suppose customers report that product pages occasionally feel frozen.",[16,822,823],{},"A useful investigation could follow this chain:",[16,825,826,829,830,833,834,837,838,841,842,845,846,849],{},[28,827,828],{},"Symptom:"," “Add to Cart” reacts slowly.\n",[28,831,832],{},"Measurement:"," Sessions with poor INP are identified.\n",[28,835,836],{},"Possible cause:"," A long client-side task or expensive application logic.\n",[28,839,840],{},"Confirmation:"," INP attribution identifies the affected interaction; the same sessions show a specific JavaScript execution path.\n",[28,843,844],{},"Fix:"," Reduce or split blocking work.\n",[28,847,848],{},"Re-measurement:"," Compare the INP distribution after the new release.",[16,851,852],{},"Another incident may begin with a high LCP, then lead to a slow image request in Resource Timing, and finally to an origin or CDN configuration issue.",[16,854,855],{},"Observability works when engineers can move between these signals without manually reconstructing the event from unrelated dashboards.",[11,857,859],{"id":858},"common-mistakes","Common Mistakes",[16,861,862,865],{},[28,863,864],{},"Tracking only averages."," Performance distributions matter. A median can hide a poor experience affecting a significant minority of users.",[16,867,868,871],{},[28,869,870],{},"Collecting errors without release information."," You need to know which deployment introduced or fixed the problem.",[16,873,874,877],{},[28,875,876],{},"Measuring Web Vitals without attribution."," Knowing that INP is 600 ms is less useful than knowing which interaction produced it.",[16,879,880,883],{},[28,881,882],{},"Logging every network request forever."," High-volume telemetry increases storage, cost and privacy exposure. Sample intelligently and retain diagnostic fields rather than indiscriminate payloads.",[16,885,886,889],{},[28,887,888],{},"Treating session replay as observability by itself."," Watching a broken session can show what happened, but errors, timings and request correlation are what explain why.",[16,891,892,895],{},[28,893,894],{},"Assuming browser telemetry is unrestricted."," Cross-origin policies, browser support and API limitations affect what can be observed.",[11,897,899],{"id":898},"seonest-recommendation","SeoNest Recommendation",[16,901,902],{},"Build frontend observability progressively.",[16,904,905],{},"Start with production error reporting and release tracking. Add real-user LCP, INP and CLS. Then collect network timing for the requests and resources that matter to your application. Finally, correlate those signals through a privacy-safe session identifier and add sampled session replay only where it provides additional diagnostic value.",[16,907,908],{},"The target architecture should let an engineer begin with a business symptom—“checkout failures increased” or “mobile product pages became slow”—and trace it toward technical evidence without guessing.",[16,910,911,912,52],{},"OpenTelemetry can help standardize traces, metrics and logs across systems, but browser instrumentation deserves special evaluation: the OpenTelemetry JavaScript documentation currently describes client-side browser instrumentation as experimental and mostly unspecified. (",[46,913,51],{"href":914,"rel":915},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Flanguages\u002Fjs\u002F?utm_source=chatgpt.com",[50],[11,917,919],{"id":918},"faq","FAQ",[921,922,924],"h4",{"id":923},"is-frontend-observability-the-same-as-monitoring","Is frontend observability the same as monitoring?",[16,926,927],{},"Not exactly. Monitoring usually answers predefined questions such as whether error rate or LCP exceeded a threshold. Observability is broader: the collected telemetry should also help investigate failures you did not anticipate in advance.",[921,929,931],{"id":930},"should-every-session-be-recorded","Should every session be recorded?",[16,933,934],{},"Usually not. Errors and lightweight RUM signals can often be collected much more broadly, while session replay can be sampled because of storage, cost and privacy considerations.",[921,936,938],{"id":937},"are-core-web-vitals-enough","Are Core Web Vitals enough?",[16,940,941],{},"No. They describe important aspects of user experience, but they do not explain every failure. Web Vitals become more useful when correlated with errors, resources, application actions and release information.",[921,943,945],{"id":944},"should-i-build-my-own-observability-platform","Should I build my own observability platform?",[16,947,948],{},"Usually, start with standard browser APIs and a proven telemetry backend. Build custom collection only where your requirements justify the engineering and operational cost.",[11,950,952],{"id":951},"final-takeaway","Final Takeaway",[16,954,955],{},"Frontend observability is not a dashboard full of browser metrics. It is a connected evidence system.",[16,957,958,959,962,963,966,967,970,971,59],{},"Errors tell you ",[28,960,961],{},"what broke",". Web Vitals tell you ",[28,964,965],{},"what users felt",". Network telemetry helps reveal ",[28,968,969],{},"where time was spent",". Session context tells you ",[28,972,973],{},"what surrounded the failure",[16,975,976],{},"When those signals share enough context, production debugging changes from trying to reproduce vague reports into investigating concrete evidence from the browser where the problem actually happened.",[11,978,980],{"id":979},"sources","Sources",[379,982,983,995,1005,1014,1023,1034,1045,1056,1064,1075],{},[382,984,985,986,990,991],{},"OpenTelemetry — ",[987,988,989],"em",{},"What is OpenTelemetry?"," Current documentation. ",[46,992,994],{"href":48,"rel":993},[50],"OpenTelemetry documentation",[382,996,985,997,1000,1001],{},[987,998,999],{},"Observability Primer",". Current documentation. ",[46,1002,999],{"href":1003,"rel":1004},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fconcepts\u002Fobservability-primer\u002F?utm_source=chatgpt.com",[50],[382,1006,1007,1008,1010,1011],{},"Google \u002F web.dev — ",[987,1009,102],{},". ",[46,1012,102],{"href":421,"rel":1013},[50],[382,1015,1007,1016,1010,1019],{},[987,1017,1018],{},"Getting Started with Measuring Web Vitals",[46,1020,1022],{"href":436,"rel":1021},[50],"Web Vitals measurement guide",[382,1024,1025,1026,1028,1029],{},"GoogleChrome — ",[987,1027,432],{}," library documentation. ",[46,1030,1033],{"href":1031,"rel":1032},"https:\u002F\u002Fgithub.com\u002FGoogleChrome\u002Fweb-vitals?utm_source=chatgpt.com",[50],"web-vitals repository and documentation",[382,1035,1036,1037,1040,1041],{},"W3C Web Performance Working Group — ",[987,1038,1039],{},"Resource Timing",", Candidate Recommendation Draft, September 1, 2026. ",[46,1042,1044],{"href":569,"rel":1043},[50],"W3C Resource Timing specification",[382,1046,1047,1048,1051,1052],{},"MDN Web Docs — ",[987,1049,1050],{},"Window: error event",", updated August 21, 2026. ",[46,1053,1055],{"href":161,"rel":1054},[50],"MDN error event documentation",[382,1057,1047,1058,1010,1060],{},[987,1059,565],{},[46,1061,1063],{"href":743,"rel":1062},[50],"MDN PerformanceResourceTiming documentation",[382,1065,1066,1067,1070,1071],{},"Ecma International — ",[987,1068,1069],{},"ECMA-426: Source map format specification",", 1st edition, December 2024. ",[46,1072,1074],{"href":360,"rel":1073},[50],"ECMA-426",[382,1076,1077,1078,1010,1081],{},"Datadog — ",[987,1079,1080],{},"Reducing Data Related Risks \u002F RUM & Session Replay",[46,1082,1084],{"href":801,"rel":1083},[50],"Datadog data security documentation",[1086,1087,1088],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":173,"searchDepth":215,"depth":215,"links":1090},[1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103],{"id":13,"depth":215,"text":14},{"id":40,"depth":215,"text":41},{"id":62,"depth":215,"text":63},{"id":143,"depth":215,"text":144},{"id":370,"depth":215,"text":371},{"id":555,"depth":215,"text":556},{"id":764,"depth":215,"text":765},{"id":813,"depth":215,"text":814},{"id":858,"depth":215,"text":859},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Web Development","Learn how frontend observability connects JavaScript errors, Core Web Vitals, network timing and session context to diagnose real user problems in production.",false,"md","\u002Ffrontend-observability.png","Image of Frontend","en",{},"\u002Fblog\u002Fen\u002Ffrontend-observability","2026-09-25",{"title":5,"description":1105},"frontend-observability","blog\u002Fen\u002Ffrontend-observability",1730,"KR8AYpyQTESYr6gkrcOyqTg8o77jP0cQSWRirBi-1fc",[1120,1121,1124],{"locale":1110,"slug":1115},{"locale":1122,"slug":1123},"ru","nablyudaemost-frontend",{"locale":1125,"slug":1126},"uz","observability-frontend",[1128,1850,2469,3284,3955,4967,5865,6699],{"id":1129,"title":1130,"author":6,"body":1131,"category":1838,"description":1839,"draft":1106,"extension":1107,"featured":280,"image":1840,"imageAlt":1841,"locale":1110,"meta":1842,"navigation":280,"path":1843,"publishedAt":1844,"readingTime":277,"seo":1845,"slug":1846,"stem":1847,"translationKey":1846,"updatedAt":1844,"wordCount":1848,"__hash__":1849},"blog\u002Fblog\u002Fen\u002F2-4-vs-5-ghz.md","2.4 GHz vs 5 GHz Wi-Fi: What’s the Difference?",{"type":8,"value":1132,"toc":1814},[1133,1136,1151,1162,1165,1169,1175,1180,1183,1187,1292,1298,1302,1308,1311,1322,1325,1329,1332,1338,1344,1347,1350,1362,1365,1370,1373,1377,1380,1383,1386,1389,1392,1396,1399,1407,1410,1421,1424,1427,1432,1436,1439,1442,1468,1474,1477,1488,1492,1495,1498,1518,1521,1524,1528,1531,1537,1540,1546,1549,1552,1562,1565,1569,1572,1578,1581,1584,1589,1592,1595,1598,1601,1606,1610,1613,1618,1621,1624,1627,1631,1636,1642,1646,1649,1653,1656,1660,1663,1665,1672,1675,1681,1684,1686,1690,1693,1697,1700,1703,1707,1710,1714,1717,1721,1729,1731,1734,1739,1742,1744],[11,1134,1130],{"id":1135},"_24-ghz-vs-5-ghz-wi-fi-whats-the-difference",[16,1137,1138,1139,1142,1143,1146,1147,1150],{},"If your router shows two Wi-Fi options—one labeled ",[28,1140,1141],{},"2.4 GHz"," and another ",[28,1144,1145],{},"5 GHz","—the number does not describe your internet plan or mobile 5G connection. It describes the ",[28,1148,1149],{},"radio-frequency band"," used between your device and the Wi-Fi access point.",[16,1152,1153,1154,624,1157,52],{},"The practical difference is straightforward: ",[28,1155,1156],{},"2.4 GHz usually reaches farther and handles obstacles better, while 5 GHz usually provides more capacity, less congestion, and higher practical speeds at shorter ranges.",[46,1158,1161],{"href":1159,"rel":1160},"https:\u002F\u002Fwww.intel.com\u002Fcontent\u002Fwww\u002Fus\u002Fen\u002Fproducts\u002Fdocs\u002Fwireless\u002F2-4-vs-5ghz.html?utm_source=chatgpt.com",[50],"intel.com",[16,1163,1164],{},"Neither band is universally better. The right choice depends on distance, walls, interference, device compatibility, and what you are doing online.",[11,1166,1168],{"id":1167},"the-short-answer","The Short Answer",[16,1170,1171,1172,1174],{},"Use ",[28,1173,1145],{}," when you are relatively close to the router and want high performance for activities such as large downloads, video calls, streaming, cloud applications, or gaming.",[16,1176,1171,1177,1179],{},[28,1178,1141],{}," when the device is farther from the router, several walls separate you from it, or you are connecting devices with modest bandwidth requirements such as some smart-home and IoT devices.",[16,1181,1182],{},"Modern dual-band routers can provide both simultaneously, so in many homes you do not actually need to choose one permanently.",[11,1184,1186],{"id":1185},"key-differences","Key Differences",[65,1188,1189,1202],{},[68,1190,1191],{},[71,1192,1193,1196,1199],{},[74,1194,1195],{},"Feature",[74,1197,1198],{},"2.4 GHz Wi-Fi",[74,1200,1201],{},"5 GHz Wi-Fi",[84,1203,1204,1215,1226,1237,1248,1259,1270,1281],{},[71,1205,1206,1209,1212],{},[89,1207,1208],{},"Typical strength",[89,1210,1211],{},"Range and compatibility",[89,1213,1214],{},"Capacity and performance",[71,1216,1217,1220,1223],{},[89,1218,1219],{},"Range",[89,1221,1222],{},"Usually longer",[89,1224,1225],{},"Usually shorter",[71,1227,1228,1231,1234],{},[89,1229,1230],{},"Obstacle penetration",[89,1232,1233],{},"Generally better",[89,1235,1236],{},"Generally weaker",[71,1238,1239,1242,1245],{},[89,1240,1241],{},"Available spectrum",[89,1243,1244],{},"More limited",[89,1246,1247],{},"Much larger",[71,1249,1250,1253,1256],{},[89,1251,1252],{},"Congestion",[89,1254,1255],{},"Usually higher",[89,1257,1258],{},"Usually lower",[71,1260,1261,1264,1267],{},[89,1262,1263],{},"Wide channels",[89,1265,1266],{},"Less practical",[89,1268,1269],{},"Much more practical",[71,1271,1272,1275,1278],{},[89,1273,1274],{},"Legacy-device support",[89,1276,1277],{},"Excellent",[89,1279,1280],{},"Depends on device",[71,1282,1283,1286,1289],{},[89,1284,1285],{},"Best suited for",[89,1287,1288],{},"Distance, IoT, basic traffic",[89,1290,1291],{},"Streaming, gaming, work, large transfers",[16,1293,1294,1295,52],{},"These are general characteristics rather than guaranteed performance figures. Actual Wi-Fi performance depends heavily on the router, client device, Wi-Fi generation, channel width, interference, signal strength, building materials, and network load. (",[46,1296,1161],{"href":1159,"rel":1297},[50],[11,1299,1301],{"id":1300},"what-does-ghz-mean","What Does GHz Mean?",[16,1303,1304,1307],{},[28,1305,1306],{},"GHz means gigahertz."," One gigahertz equals one billion cycles per second.",[16,1309,1310],{},"In this context, 2.4 GHz and 5 GHz describe different parts of the radio-frequency spectrum that Wi-Fi equipment can use.",[16,1312,1313,1314,1317,1318,1321],{},"This is unrelated to ",[28,1315,1316],{},"4G or 5G mobile networks",". In “5G,” the G means ",[987,1319,1320],{},"generation",". In “5 GHz,” GHz is a measurement of frequency.",[16,1323,1324],{},"You can think of 2.4 GHz and 5 GHz as two different roads connecting your device to the router. Both ultimately lead to the same network, but their physical characteristics and available capacity differ.",[11,1326,1328],{"id":1327},"why-5-ghz-is-usually-faster","Why 5 GHz Is Usually Faster",[16,1330,1331],{},"A common explanation is that “higher frequency means faster Wi-Fi.” That is incomplete.",[16,1333,1334,1335,59],{},"The frequency itself is not simply a speed control. One major reason 5 GHz networks can provide higher throughput is that the band offers ",[28,1336,1337],{},"far more usable spectrum and more opportunities for wider channels",[16,1339,1340,1341,52],{},"Intel describes the 2.4 GHz Wi-Fi spectrum as roughly 70 MHz wide, while the commonly used 5 GHz spectrum provides substantially more spectrum. This gives 5 GHz networks more room to operate without forcing nearby networks into the same limited set of channels. (",[46,1342,1161],{"href":1159,"rel":1343},[50],[16,1345,1346],{},"Channel width matters as well.",[16,1348,1349],{},"A channel can be thought of as a lane allocated to a Wi-Fi transmission. Wider channels can carry more data under suitable conditions.",[16,1351,1352,1353,1356,1357,52],{},"Apple currently recommends ",[28,1354,1355],{},"20 MHz channel width for 2.4 GHz",", particularly because wider configurations can increase interference and reliability problems in crowded environments. For 5 GHz, Apple recommends allowing automatic or supported channel widths so compatible devices can take advantage of greater available bandwidth. (",[46,1358,1361],{"href":1359,"rel":1360},"https:\u002F\u002Fsupport.apple.com\u002Fen-ae\u002F102766?utm_source=chatgpt.com",[50],"support.apple.com",[16,1363,1364],{},"So the more useful model is:",[16,1366,1367],{},[28,1368,1369],{},"5 GHz → more available spectrum → more usable channels and wider channels → potentially greater network capacity.",[16,1371,1372],{},"That does not mean every 5 GHz connection will outperform every 2.4 GHz connection. A weak 5 GHz signal through several walls can perform worse than a strong 2.4 GHz connection.",[11,1374,1376],{"id":1375},"why-24-ghz-reaches-farther","Why 2.4 GHz Reaches Farther",[16,1378,1379],{},"Radio propagation changes with frequency.",[16,1381,1382],{},"Under comparable conditions, lower-frequency signals generally experience lower free-space loss and tend to provide better coverage through distance and obstacles than higher-frequency Wi-Fi signals. In normal home use, this means 2.4 GHz often remains usable farther from the router.",[16,1384,1385],{},"Imagine your router is in the living room.",[16,1387,1388],{},"Your laptop beside the router may get excellent performance on 5 GHz. Move two rooms away, place several walls between you and the access point, and the 5 GHz signal may weaken significantly. Switching to 2.4 GHz may produce a stronger and more stable connection even if its maximum potential throughput is lower.",[16,1390,1391],{},"Building materials also matter. Concrete, reinforced walls, metal, mirrors, and other structures can significantly affect radio signals, so there is no universal distance at which you should switch bands.",[11,1393,1395],{"id":1394},"why-24-ghz-gets-crowded","Why 2.4 GHz Gets Crowded",[16,1397,1398],{},"The 2.4 GHz band is used by far more than Wi-Fi.",[16,1400,1401,1402,52],{},"Bluetooth devices and other consumer electronics can operate in the same general spectrum. Nearby Wi-Fi networks also compete for airtime. Cisco notes that 2.4 GHz is commonly congested and can experience interference from devices including Bluetooth equipment and microwave ovens. (",[46,1403,1406],{"href":1404,"rel":1405},"https:\u002F\u002Fwww.cisco.com\u002Fc\u002Fen\u002Fus\u002Fsupport\u002Fdocs\u002Fsmb\u002Fwireless\u002FCB-Wireless-Mesh\u002F2069-tz-Changing-RF-Channels.html?utm_source=chatgpt.com",[50],"cisco.com",[16,1408,1409],{},"The channel situation makes the problem more noticeable.",[16,1411,1412,1413,1416,1417,52],{},"In the commonly used 20 MHz configuration, channels ",[28,1414,1415],{},"1, 6, and 11"," are the traditional non-overlapping 2.4 GHz channel arrangement in regulatory domains where those channels are available. Cisco documentation discusses these channels specifically when planning nearby access points to reduce overlap. (",[46,1418,1406],{"href":1419,"rel":1420},"https:\u002F\u002Fwww.cisco.com\u002Fc\u002Fen\u002Fus\u002Ftd\u002Fdocs\u002Frouters\u002Faccess\u002F1900\u002Fsoftware\u002Fconfiguration\u002Fguide\u002FSoftware_Configuration\u002Fradio_config.html?utm_source=chatgpt.com",[50],[16,1422,1423],{},"Imagine an apartment building with 20 routers around you. If most of them are using the same small section of 2.4 GHz spectrum, the devices must share airtime.",[16,1425,1426],{},"Your ISP connection could be 1 Gbps and the Wi-Fi experience could still be poor because the bottleneck is the local wireless environment rather than the internet connection itself.",[16,1428,1429],{},[177,1430,1431],{},"INTERNAL LINK: Why Wi-Fi Can Be Slow Even With Fast Internet",[11,1433,1435],{"id":1434},"when-to-use-5-ghz","When to Use 5 GHz",[16,1437,1438],{},"Choose 5 GHz when you have a strong enough signal and performance matters.",[16,1440,1441],{},"Typical cases include:",[379,1443,1444,1447,1450,1453,1456,1459,1462,1465],{},[382,1445,1446],{},"laptops and desktop computers near the router;",[382,1448,1449],{},"4K video streaming;",[382,1451,1452],{},"large file transfers;",[382,1454,1455],{},"cloud backups;",[382,1457,1458],{},"video conferencing;",[382,1460,1461],{},"game downloads;",[382,1463,1464],{},"low-latency applications;",[382,1466,1467],{},"high-bandwidth home-office workloads.",[16,1469,1470,1471,52],{},"Intel also recommends higher-frequency Wi-Fi bands for demanding real-time workloads such as gaming, streaming, videoconferencing, and productivity applications. (",[46,1472,1161],{"href":1159,"rel":1473},[50],[16,1475,1476],{},"There is another advantage: because 5 GHz provides substantially more channel capacity, neighboring access points have more room to avoid each other.",[16,1478,1479,1480,1483,1484,52],{},"Some 5 GHz channels are subject to ",[28,1481,1482],{},"Dynamic Frequency Selection (DFS)"," rules because the spectrum is shared with radar systems. An access point operating on a DFS channel may have to detect radar and move to another channel when necessary. Exact channel availability and DFS requirements depend on the regulatory domain. (",[46,1485,1406],{"href":1486,"rel":1487},"https:\u002F\u002Fwww.cisco.com\u002Fc\u002Fen\u002Fus\u002Fsupport\u002Fdocs\u002Fwireless-mobility\u002F80211\u002F213882-radar-detection-in-dynamic-frequency-sel.html?utm_source=chatgpt.com",[50],[11,1489,1491],{"id":1490},"when-to-use-24-ghz","When to Use 2.4 GHz",[16,1493,1494],{},"2.4 GHz remains extremely useful.",[16,1496,1497],{},"It is often the better choice when:",[379,1499,1500,1503,1506,1509,1512,1515],{},[382,1501,1502],{},"the device is far from the router;",[382,1504,1505],{},"multiple walls separate the device and access point;",[382,1507,1508],{},"the device only supports 2.4 GHz;",[382,1510,1511],{},"bandwidth requirements are low;",[382,1513,1514],{},"you are connecting smart bulbs, sensors, thermostats, or similar IoT equipment;",[382,1516,1517],{},"5 GHz signal strength is poor.",[16,1519,1520],{},"Many IoT devices support only 2.4 GHz because they do not need enormous bandwidth and benefit from broad compatibility and coverage.",[16,1522,1523],{},"That does not make 2.4 GHz obsolete. It simply serves a different role.",[11,1525,1527],{"id":1526},"should-you-separate-the-wi-fi-names","Should You Separate the Wi-Fi Names?",[16,1529,1530],{},"You may have seen networks such as:",[168,1532,1535],{"className":1533,"code":1534,"language":787,"meta":173},[785],"HomeWiFi_2.4\n",[20,1536,1534],{"__ignoreMap":173},[16,1538,1539],{},"and",[168,1541,1544],{"className":1542,"code":1543,"language":787,"meta":173},[785],"HomeWiFi_5G\n",[20,1545,1543],{"__ignoreMap":173},[16,1547,1548],{},"This allows you to select the band manually, but it is not always necessary.",[16,1550,1551],{},"Modern routers frequently support band steering or similar mechanisms that allow devices to use one network name while the router and client determine an appropriate band.",[16,1553,1554,1555,1558,1559,52],{},"Apple currently recommends using ",[28,1556,1557],{},"one unique SSID across all supported Wi-Fi bands",", rather than assigning separate names to 2.4 GHz, 5 GHz, and 6 GHz networks. (",[46,1560,1361],{"href":1359,"rel":1561},[50],[16,1563,1564],{},"Manual separation can still be useful for troubleshooting, testing, older devices, or situations where you deliberately want to force a device onto a specific band.",[11,1566,1568],{"id":1567},"ghz-is-not-your-internet-speed","GHz Is Not Your Internet Speed",[16,1570,1571],{},"One of the most important misconceptions is:",[1573,1574,1575],"blockquote",{},[16,1576,1577],{},"“5 GHz means my internet will be faster.”",[16,1579,1580],{},"Not necessarily.",[16,1582,1583],{},"Your connection contains several separate performance limits:",[16,1585,1586],{},[28,1587,1588],{},"Device → Wi-Fi → router → ISP connection → Internet destination",[16,1590,1591],{},"Suppose your internet plan provides 100 Mbps.",[16,1593,1594],{},"Even if the Wi-Fi link between your laptop and router is theoretically capable of hundreds of megabits per second, an internet download cannot exceed the limits imposed elsewhere in the path.",[16,1596,1597],{},"Likewise, upgrading from 2.4 GHz to 5 GHz cannot fix a slow server or a congested ISP connection.",[16,1599,1600],{},"But if Wi-Fi itself is the bottleneck, changing bands can produce a substantial improvement.",[16,1602,1603],{},[177,1604,1605],{},"INTERNAL LINK: Wi-Fi Speed vs Internet Speed Explained",[11,1607,1609],{"id":1608},"how-to-choose","How to Choose",[16,1611,1612],{},"A useful decision rule is:",[16,1614,1615],{},[28,1616,1617],{},"Start with 5 GHz. Move to 2.4 GHz when range or stability becomes more important than maximum throughput.",[16,1619,1620],{},"If the router automatically manages both bands under one SSID, leaving the decision to modern client and router algorithms is often reasonable.",[16,1622,1623],{},"For a fixed device that performs poorly, test both bands rather than assuming one is better.",[16,1625,1626],{},"Measure actual performance in the device's real location. A speed test, latency measurement, signal-strength reading, or local file-transfer test will tell you more than the GHz label alone.",[11,1628,1630],{"id":1629},"common-misconceptions","Common Misconceptions",[1632,1633,1635],"h3",{"id":1634},"_5-ghz-means-5g","5 GHz means 5G",[16,1637,1638,1639],{},"No. ",[28,1640,1641],{},"5 GHz is a radio frequency. 5G is a generation of cellular technology.",[1632,1643,1645],{"id":1644},"_5-ghz-is-always-faster","5 GHz is always faster",[16,1647,1648],{},"No. It has greater performance potential, but a weak 5 GHz signal can be worse than a strong 2.4 GHz connection.",[1632,1650,1652],{"id":1651},"_24-ghz-is-outdated","2.4 GHz is outdated",[16,1654,1655],{},"No. It remains valuable for coverage, legacy compatibility, and many low-bandwidth devices.",[1632,1657,1659],{"id":1658},"a-stronger-wi-fi-signal-means-faster-internet","A stronger Wi-Fi signal means faster internet",[16,1661,1662],{},"Not necessarily. Signal quality only describes part of the path. ISP speed, congestion, device capability, router hardware, and remote servers can all become bottlenecks.",[11,1664,899],{"id":898},[16,1666,1667,1668,1671],{},"For a modern dual-band network, keep ",[28,1669,1670],{},"both 2.4 GHz and 5 GHz enabled"," unless you have a specific reason not to.",[16,1673,1674],{},"Use 5 GHz as the preferred performance band for modern laptops, phones, TVs, consoles, and work devices when signal strength is sufficient. Keep 2.4 GHz available for longer-range coverage and devices that need it.",[16,1676,1677,1678,52],{},"Use automatic channel selection when it works well in your environment. For 2.4 GHz, 20 MHz channel width is generally the safer configuration in crowded areas; wider channel options are more practical on 5 GHz. Apple currently recommends this general setup for modern Wi-Fi networks. (",[46,1679,1361],{"href":1359,"rel":1680},[50],[16,1682,1683],{},"Most importantly, optimize based on actual measurements rather than assuming that the larger frequency number automatically means a better connection.",[11,1685,919],{"id":918},[921,1687,1689],{"id":1688},"is-24-ghz-or-5-ghz-better-through-walls","Is 2.4 GHz or 5 GHz better through walls?",[16,1691,1692],{},"2.4 GHz generally provides better range through walls and other obstacles. The real difference varies substantially with wall material, building layout, antennas, transmit power, and interference.",[921,1694,1696],{"id":1695},"which-band-is-better-for-gaming","Which band is better for gaming?",[16,1698,1699],{},"5 GHz is usually preferable when the router is nearby because it can provide greater capacity and less interference. If the 5 GHz signal is weak, however, 2.4 GHz may provide the more stable connection.",[16,1701,1702],{},"For latency-sensitive gaming, wired Ethernet remains preferable when practical.",[921,1704,1706],{"id":1705},"which-band-should-smart-home-devices-use","Which band should smart-home devices use?",[16,1708,1709],{},"Many smart-home and IoT devices use 2.4 GHz. Their bandwidth requirements are typically small, while range and device compatibility matter more.",[921,1711,1713],{"id":1712},"can-a-router-use-both-bands-at-once","Can a router use both bands at once?",[16,1715,1716],{},"Yes. A dual-band router can provide 2.4 GHz and 5 GHz networks simultaneously.",[921,1718,1720],{"id":1719},"does-5-ghz-have-more-channels","Does 5 GHz have more channels?",[16,1722,1723,1724,52],{},"Yes. One major advantage of the 5 GHz band is significantly greater available spectrum and a larger number of usable channel configurations, although exact channels vary by country and regulatory domain. (",[46,1725,1728],{"href":1726,"rel":1727},"https:\u002F\u002Fteam-development.cisco.com\u002Fc\u002Fen\u002Fus\u002Fsupport\u002Fdocs\u002Fsmb\u002Fwireless\u002FCB-Wireless-Mesh\u002F1776-CBW-PID-Decoder.html?utm_source=chatgpt.com",[50],"team-development.cisco.com",[11,1730,952],{"id":951},[16,1732,1733],{},"The difference between 2.4 GHz and 5 GHz Wi-Fi is not simply “slow versus fast.”",[16,1735,1736],{},[28,1737,1738],{},"2.4 GHz prioritizes reach and compatibility. 5 GHz provides more spectrum and usually enables higher-capacity connections when signal conditions are good.",[16,1740,1741],{},"For most modern networks, the best solution is not choosing one and disabling the other. It is using both for the jobs they handle best.",[11,1743,980],{"id":979},[1745,1746,1747,1756,1765,1774,1783,1794,1803],"ol",{},[382,1748,1749,1752,1753,52],{},[28,1750,1751],{},"Intel — “2.4 GHz vs. 5 GHz vs. 6 GHz: What’s the Difference?”","\nExplanation of Wi-Fi frequency bands, spectrum capacity, range, congestion, channel widths, and practical use cases. (",[46,1754,1161],{"href":1159,"rel":1755},[50],[382,1757,1758,1761,1762,52],{},[28,1759,1760],{},"Apple Support — “Recommended settings for Wi-Fi routers and access points”","\nCurrent recommendations for common SSIDs, automatic channel selection, 20 MHz 2.4 GHz channels, and automatic\u002Fall supported channel widths on 5 GHz and 6 GHz. (",[46,1763,1361],{"href":1359,"rel":1764},[50],[382,1766,1767,1770,1771,52],{},[28,1768,1769],{},"Cisco — “RF Channels on a Cisco Business Wireless Network”","\nPractical documentation covering congestion, interference, 2.4 GHz behavior, and Wi-Fi channel selection. (",[46,1772,1406],{"href":1404,"rel":1773},[50],[382,1775,1776,1779,1780,52],{},[28,1777,1778],{},"Cisco — Software Configuration Guide: Configuring the Radio","\nDocumentation covering channel allocation and the common 1\u002F6\u002F11 non-overlapping 2.4 GHz channel plan. (",[46,1781,1406],{"href":1419,"rel":1782},[50],[382,1784,1785,1788,1789,52],{},[28,1786,1787],{},"Cisco — Wireless RF Reference Guide","\nTechnical reference covering 5 GHz spectrum, channel allocation, U-NII ranges, and DFS usage. (",[46,1790,1793],{"href":1791,"rel":1792},"https:\u002F\u002Fspg.xgslb-v3.cisco.com\u002Fc\u002Fen\u002Fus\u002Ftd\u002Fdocs\u002Fwireless\u002Fcontroller\u002F9800\u002Ftechnical-reference\u002Fwireless-rf-reference-guide.html?utm_source=chatgpt.com",[50],"spg.xgslb-v3.cisco.com",[382,1795,1796,1799,1800,52],{},[28,1797,1798],{},"Cisco — “Identify Radar Detection in Dynamic Frequency Selection (DFS) Channels”",", updated June 7, 2023.\nExplanation of DFS requirements and radar detection on applicable 5 GHz channels. (",[46,1801,1406],{"href":1486,"rel":1802},[50],[382,1804,1805,1808,1809,52],{},[28,1806,1807],{},"Federal Communications Commission — 5 GHz U-NII spectrum documentation","\nRegulatory background covering unlicensed wireless operation within relevant 5 GHz spectrum ranges. (",[46,1810,1813],{"href":1811,"rel":1812},"https:\u002F\u002Fdocs.fcc.gov\u002Fpublic\u002Fattachments\u002FFCC-03-287A3.pdf?utm_source=chatgpt.com",[50],"docs.fcc.gov",{"title":173,"searchDepth":215,"depth":215,"links":1815},[1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1834,1835,1836,1837],{"id":1135,"depth":215,"text":1130},{"id":1167,"depth":215,"text":1168},{"id":1185,"depth":215,"text":1186},{"id":1300,"depth":215,"text":1301},{"id":1327,"depth":215,"text":1328},{"id":1375,"depth":215,"text":1376},{"id":1394,"depth":215,"text":1395},{"id":1434,"depth":215,"text":1435},{"id":1490,"depth":215,"text":1491},{"id":1526,"depth":215,"text":1527},{"id":1567,"depth":215,"text":1568},{"id":1608,"depth":215,"text":1609},{"id":1629,"depth":215,"text":1630,"children":1829},[1830,1831,1832,1833],{"id":1634,"depth":224,"text":1635},{"id":1644,"depth":224,"text":1645},{"id":1651,"depth":224,"text":1652},{"id":1658,"depth":224,"text":1659},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Technical SEO","Learn the difference between 2.4 GHz and 5 GHz Wi-Fi, including speed, range, interference, channels, walls, gaming, and which band you should use.","\u002F2-4-vs-5-ghz.png","Image of GHz",{},"\u002Fblog\u002Fen\u002F2-4-vs-5-ghz","2026-09-30",{"title":1130,"description":1839},"2-4-vs-5-ghz","blog\u002Fen\u002F2-4-vs-5-ghz",2081,"QKZ_yDhZ586pQSUaGIMlbrmB_VfUjWUUGC-5wIkVbYg",{"id":1851,"title":1852,"author":6,"body":1853,"category":1838,"description":2459,"draft":1106,"extension":1107,"featured":280,"image":2460,"imageAlt":2461,"locale":1110,"meta":2462,"navigation":280,"path":2463,"publishedAt":1844,"readingTime":265,"seo":2464,"slug":2465,"stem":2466,"translationKey":2465,"updatedAt":1844,"wordCount":2467,"__hash__":2468},"blog\u002Fblog\u002Fen\u002Fcrawl-budget.md","Crawl Budget: When It Matters and How to Optimize It",{"type":8,"value":1854,"toc":2435},[1855,1859,1862,1865,1868,1872,1879,1882,1896,1899,1906,1910,1913,1962,1965,1968,1971,1976,1979,1984,1988,1991,1994,1997,2000,2027,2030,2034,2037,2040,2060,2063,2066,2071,2076,2081,2084,2087,2090,2095,2099,2105,2111,2115,2122,2128,2133,2137,2140,2145,2149,2152,2170,2175,2179,2182,2192,2195,2199,2202,2207,2213,2218,2224,2229,2235,2238,2240,2244,2247,2251,2254,2257,2261,2264,2267,2271,2273,2276,2278,2281,2284,2287,2290,2296,2298,2302,2305,2309,2312,2316,2319,2323,2326,2330,2333,2335,2338,2341,2347,2349],[11,1856,1858],{"id":1857},"crawl-budget-when-it-matters-and-when-it-does-not","Crawl Budget: When It Matters and When It Does Not",[16,1860,1861],{},"Crawl budget is one of those SEO concepts that sounds important for every website but usually is not.",[16,1863,1864],{},"If you run a small company website, a portfolio, a blog with a few hundred posts, or even many ordinary content sites, you probably do not need to “optimize crawl budget.” Google explicitly says its crawl-budget guidance is mainly intended for very large or rapidly changing sites. If your new or updated pages are already being crawled promptly, crawl budget is unlikely to be the problem.",[16,1866,1867],{},"The subject becomes important when a site produces far more crawlable URLs than Google can efficiently revisit: large ecommerce catalogs, marketplaces, publishers, classified sites, or platforms where filters and parameters can generate enormous URL spaces.",[11,1869,1871],{"id":1870},"what-is-crawl-budget","What Is Crawl Budget?",[16,1873,1874,1875,1878],{},"Crawl budget describes the set of URLs Google ",[28,1876,1877],{},"can and wants to crawl"," on a website within a period of time.",[16,1880,1881],{},"Google explains this through two main concepts:",[379,1883,1884,1890],{},[382,1885,1886,1889],{},[28,1887,1888],{},"Crawl capacity"," — how much crawling Googlebot can perform without overwhelming the website or Google's own crawling infrastructure.",[382,1891,1892,1895],{},[28,1893,1894],{},"Crawl demand"," — how much Google wants to crawl particular URLs based on factors such as their perceived importance and how stale Google's existing version may be.",[16,1897,1898],{},"Together, these determine how much crawling actually happens. Having unused server capacity does not mean Google will automatically crawl more pages; crawl demand may simply be lower.",[16,1900,1901,1902,1905],{},"Crawling should also not be confused with indexing. Google can crawl a URL without indexing it. A successful ",[20,1903,1904],{},"200"," response only makes the content eligible for further processing; it does not guarantee inclusion in Google's index.",[11,1907,1909],{"id":1908},"when-crawl-budget-matters","When Crawl Budget Matters",[16,1911,1912],{},"Google's current guidance primarily targets three situations:",[65,1914,1915,1925],{},[68,1916,1917],{},[71,1918,1919,1922],{},[74,1920,1921],{},"Site situation",[74,1923,1924],{},"Crawl budget relevance",[84,1926,1927,1935,1943,1954],{},[71,1928,1929,1932],{},[89,1930,1931],{},"More than roughly 1 million unique pages, with content changing around weekly",[89,1933,1934],{},"High",[71,1936,1937,1940],{},[89,1938,1939],{},"More than roughly 10,000 unique pages, with content changing daily",[89,1941,1942],{},"Potentially high",[71,1944,1945,1951],{},[89,1946,1947,1948],{},"Many URLs reported as ",[28,1949,1950],{},"Discovered – currently not indexed",[89,1952,1953],{},"Worth investigating",[71,1955,1956,1959],{},[89,1957,1958],{},"Small or moderately sized site whose pages are crawled promptly",[89,1960,1961],{},"Usually low",[16,1963,1964],{},"Google describes these page counts as approximate examples rather than strict thresholds.",[16,1966,1967],{},"That distinction matters. A 20,000-page ecommerce site whose inventory changes every few hours may face a real crawling problem, while a 100,000-page archive containing mostly stable documents may not.",[16,1969,1970],{},"The relevant question is therefore not simply:",[16,1972,1973],{},[28,1974,1975],{},"“How many pages does my website have?”",[16,1977,1978],{},"It is:",[16,1980,1981],{},[28,1982,1983],{},"“Is inefficient crawling preventing Google from discovering or refreshing URLs that actually matter?”",[11,1985,1987],{"id":1986},"when-it-does-not-matter","When It Does Not Matter",[16,1989,1990],{},"For many websites, crawl budget should be far down the SEO priority list.",[16,1992,1993],{},"If Google is finding new pages quickly, recrawling important updates, and you do not see systemic discovery problems, there is little reason to spend engineering time trying to increase Googlebot activity.",[16,1995,1996],{},"Google specifically says that sites without many rapidly changing pages, or sites whose pages are generally crawled on the day they are published, normally only need to keep their sitemap current and monitor indexing.",[16,1998,1999],{},"In those cases, problems attributed to “crawl budget” may actually involve something else:",[379,2001,2002,2005,2012,2015,2018,2021,2024],{},[382,2003,2004],{},"weak internal linking;",[382,2006,2007,2008,2011],{},"accidental ",[20,2009,2010],{},"robots.txt"," restrictions;",[382,2013,2014],{},"poor canonicalization;",[382,2016,2017],{},"low-value or duplicate pages;",[382,2019,2020],{},"server errors;",[382,2022,2023],{},"rendering problems;",[382,2025,2026],{},"pages Google discovered but decided not to index.",[16,2028,2029],{},"Crawling is only one stage of Google Search. Discovery, rendering, canonicalization, indexing, quality evaluation, and serving are separate processes.",[11,2031,2033],{"id":2032},"how-crawl-budget-gets-wasted","How Crawl Budget Gets Wasted",[16,2035,2036],{},"The most common problem is not that Google receives too little crawl budget. It is that the site exposes too many unnecessary URLs.",[16,2038,2039],{},"Consider an ecommerce category with filters for:",[379,2041,2042,2045,2048,2051,2054,2057],{},[382,2043,2044],{},"color;",[382,2046,2047],{},"size;",[382,2049,2050],{},"brand;",[382,2052,2053],{},"price;",[382,2055,2056],{},"availability;",[382,2058,2059],{},"sorting order.",[16,2061,2062],{},"A single category can generate thousands or millions of URL combinations.",[16,2064,2065],{},"For example:",[16,2067,2068],{},[20,2069,2070],{},"\u002Fshoes?color=black&size=42&sort=price",[16,2072,2073],{},[20,2074,2075],{},"\u002Fshoes?size=42&color=black&sort=price",[16,2077,2078],{},[20,2079,2080],{},"\u002Fshoes?sort=price&color=black&size=42",[16,2082,2083],{},"Those URLs may represent substantially the same content while still looking like separate crawl targets.",[16,2085,2086],{},"Google's documentation warns that faceted navigation can create effectively unbounded URL spaces. Crawlers may need to request many of those URLs before determining that they provide little value, leaving less crawling capacity for useful new URLs.",[16,2088,2089],{},"Duplicate content creates a similar problem. Google normally groups duplicate or very similar pages and selects a canonical representative. Duplicate versions are generally crawled less frequently, but Google must still discover and process enough of them to understand the relationship.",[16,2091,2092],{},[177,2093,2094],{},"INTERNAL LINK: URL Parameters and Faceted Navigation for SEO",[11,2096,2098],{"id":2097},"improve-crawl-efficiency","Improve Crawl Efficiency",[16,2100,2101,2102],{},"The goal should not be ",[28,2103,2104],{},"“make Google crawl more.”",[16,2106,2107,2108],{},"It should be ",[28,2109,2110],{},"“make useful URLs easier to find and unnecessary URL spaces harder to create.”",[1632,2112,2114],{"id":2113},"control-duplicate-urls","Control duplicate URLs",[16,2116,2117,2118,2121],{},"Use redirects, consistent internal linking, ",[20,2119,2120],{},"rel=\"canonical\"",", and clean sitemap URLs where appropriate.",[16,2123,2124,2125,2127],{},"Google describes redirects and ",[20,2126,2120],{}," as stronger canonicalization signals, while sitemap inclusion is a weaker signal. Canonicalization can also reduce time spent crawling duplicate versions.",[16,2129,2130],{},[177,2131,2132],{},"INTERNAL LINK: Canonical URLs Explained",[1632,2134,2136],{"id":2135},"control-unnecessary-crawl-paths","Control unnecessary crawl paths",[16,2138,2139],{},"If filter or parameter URLs do not need to appear in search, avoid exposing effectively unlimited crawlable combinations.",[16,2141,2142,2144],{},[20,2143,2010],{}," can prevent Googlebot from requesting selected paths, although blocking crawling is not the same as guaranteeing that a URL cannot appear in search. A blocked URL can still potentially be known from external links.",[1632,2146,2148],{"id":2147},"keep-sitemaps-accurate","Keep sitemaps accurate",[16,2150,2151],{},"Sitemaps should contain the URLs you actually want search engines to discover.",[16,2153,2154,2155,2158,2159,2161,2162,2165,2166,2169],{},"For large or frequently updated sites, accurate ",[20,2156,2157],{},"\u003Clastmod>"," values can also provide useful change information. Google says it uses ",[20,2160,2157],{}," when the value is consistently and verifiably accurate and reflects a significant page update. Google ignores sitemap ",[20,2163,2164],{},"\u003Cpriority>"," and ",[20,2167,2168],{},"\u003Cchangefreq>"," values.",[16,2171,2172],{},[177,2173,2174],{},"INTERNAL LINK: XML Sitemaps for SEO",[1632,2176,2178],{"id":2177},"keep-servers-healthy","Keep servers healthy",[16,2180,2181],{},"Server reliability directly affects crawling.",[16,2183,2184,2185,2165,2188,2191],{},"Google treats ",[20,2186,2187],{},"429",[20,2189,2190],{},"5xx"," responses as signals that the server may be overloaded and temporarily reduces crawling. Once successful responses resume, crawl rate can gradually increase again.",[16,2193,2194],{},"That means performance infrastructure can become part of crawl management on very large sites—not because faster pages automatically rank better, but because unstable infrastructure can constrain Google's ability to fetch them reliably.",[11,2196,2198],{"id":2197},"a-practical-diagnostic","A Practical Diagnostic",[16,2200,2201],{},"Before calling something a crawl-budget problem, check the sequence:",[16,2203,2204,2206],{},[28,2205,828],{}," Important URLs are discovered late or refreshed too slowly.",[16,2208,2209,2212],{},[28,2210,2211],{},"Measure:"," Look at indexing patterns, sitemap coverage, important URL samples, server logs, and Googlebot activity.",[16,2214,2215,2217],{},[28,2216,836],{}," Googlebot is spending substantial crawling activity on duplicates, parameters, obsolete URLs, or endless filter combinations.",[16,2219,2220,2223],{},[28,2221,2222],{},"Confirm:"," Compare crawl activity for useful URL groups against low-value URL groups.",[16,2225,2226,2228],{},[28,2227,844],{}," Reduce unnecessary URL generation, improve canonicalization and internal linking, clean up sitemaps, and resolve server errors.",[16,2230,2231,2234],{},[28,2232,2233],{},"Re-measure:"," Determine whether important URLs are being discovered and revisited more consistently.",[16,2236,2237],{},"Simply seeing Googlebot crawl “unimportant” pages does not prove that crawl budget is limiting important ones. Google notes that preventing some URLs from being recrawled does not automatically transfer crawl resources elsewhere unless the site is already approaching its serving limits.",[11,2239,1630],{"id":1629},[1632,2241,2243],{"id":2242},"every-website-has-to-optimize-crawl-budget","“Every website has to optimize crawl budget”",[16,2245,2246],{},"No. Google positions crawl-budget optimization as advanced guidance mainly for large and frequently changing websites.",[1632,2248,2250],{"id":2249},"more-crawling-means-better-rankings","“More crawling means better rankings”",[16,2252,2253],{},"There is no documented rule that increasing crawl volume improves rankings.",[16,2255,2256],{},"Crawling makes processing possible; it is not itself a ranking reward.",[1632,2258,2260],{"id":2259},"canonical-tags-stop-crawling","“Canonical tags stop crawling”",[16,2262,2263],{},"Not directly.",[16,2265,2266],{},"A canonical annotation signals which URL you prefer as the representative version. Over time, duplicates may be crawled less frequently, but a canonical tag is not a crawling prohibition.",[1632,2268,2270],{"id":2269},"i-should-block-every-low-value-url","“I should block every low-value URL”",[16,2272,1580],{},[16,2274,2275],{},"Some URLs need to remain crawlable so Google can understand redirects, canonical relationships, or indexing directives. Crawl controls should therefore solve a measured problem rather than become a blanket cleanup exercise.",[11,2277,899],{"id":898},[16,2279,2280],{},"Do not begin with crawl-budget optimization.",[16,2282,2283],{},"Begin by asking whether important pages are genuinely suffering from delayed discovery or recrawling.",[16,2285,2286],{},"For ordinary sites, maintain clean internal links, valid sitemaps, sensible canonicalization, stable servers, and a controlled URL structure. That is usually enough.",[16,2288,2289],{},"For large ecommerce sites, marketplaces, publishers, or platforms generating huge numbers of parameterized URLs, treat crawling as an engineering resource. Inspect what Googlebot actually requests, identify unnecessary URL spaces, and optimize the architecture so crawl activity concentrates on URLs that can provide unique search value.",[16,2291,2292,2293],{},"The difference is important: ",[28,2294,2295],{},"crawl budget is usually not something to increase. It is something to stop wasting when scale makes waste consequential.",[11,2297,919],{"id":918},[921,2299,2301],{"id":2300},"does-crawl-budget-affect-seo","Does crawl budget affect SEO?",[16,2303,2304],{},"Indirectly, it can. If important pages are not crawled or refreshed efficiently, Google cannot process their newest content. But crawl budget is not itself a documented ranking factor.",[921,2306,2308],{"id":2307},"how-large-must-a-site-be-before-crawl-budget-matters","How large must a site be before crawl budget matters?",[16,2310,2311],{},"There is no strict threshold. Google's approximate examples include sites above one million pages with weekly-changing content and sites above 10,000 pages with daily-changing content.",[921,2313,2315],{"id":2314},"can-a-sitemap-increase-crawl-budget","Can a sitemap increase crawl budget?",[16,2317,2318],{},"A sitemap helps Google discover important URLs and understand changes, but it does not guarantee additional crawl capacity or indexing.",[921,2320,2322],{"id":2321},"can-robotstxt-save-crawl-budget","Can robots.txt save crawl budget?",[16,2324,2325],{},"It can prevent Googlebot from requesting selected URL paths and may therefore reduce unnecessary crawling. However, it should be used deliberately because blocking crawling also prevents Google from seeing page-level content and directives on those URLs.",[921,2327,2329],{"id":2328},"should-small-websites-worry-about-crawl-budget","Should small websites worry about crawl budget?",[16,2331,2332],{},"Usually not. If important pages are discovered and crawled promptly, other technical and content issues are likely to deserve attention first.",[11,2334,952],{"id":951},[16,2336,2337],{},"Crawl budget becomes an SEO problem when the number and change rate of crawlable URLs are large enough that Google spends meaningful resources on URLs you do not care about while important URLs wait.",[16,2339,2340],{},"For most websites, that situation never occurs.",[16,2342,2343,2344,59],{},"For sites operating at large scale, however, URL architecture, canonicalization, faceted navigation, sitemaps, server reliability, and crawl behavior become closely connected engineering concerns. The right objective is not maximum crawling. It is ",[28,2345,2346],{},"efficient crawling of the URLs that matter",[11,2348,980],{"id":979},[1745,2350,2351,2363,2375,2385,2395,2405,2415,2425],{},[382,2352,2353,2354,2357,2358],{},"Google — ",[28,2355,2356],{},"Optimize your crawl budget",", Google Crawling Infrastructure. Current documentation; migrated to the Crawling Infrastructure documentation on December 18, 2025.\n",[46,2359,2362],{"href":2360,"rel":2361},"https:\u002F\u002Fdevelopers.google.com\u002Fcrawling\u002Fdocs\u002Fcrawl-budget?utm_source=chatgpt.com",[50],"Google crawl budget documentation",[382,2364,2365,2366,2369,2370],{},"Google Search Central — ",[28,2367,2368],{},"In-Depth Guide to How Google Search Works",".\n",[46,2371,2374],{"href":2372,"rel":2373},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Ffundamentals\u002Fhow-search-works?utm_source=chatgpt.com",[50],"How Google Search works",[382,2376,2353,2377,2369,2380],{},[28,2378,2379],{},"Managing crawling of faceted navigation URLs",[46,2381,2384],{"href":2382,"rel":2383},"https:\u002F\u002Fdevelopers.google.com\u002Fcrawling\u002Fdocs\u002Ffaceted-navigation?utm_source=chatgpt.com",[50],"Faceted navigation crawling guidance",[382,2386,2365,2387,2369,2390],{},[28,2388,2389],{},"How to specify a canonical URL with rel=\"canonical\" and other methods",[46,2391,2394],{"href":2392,"rel":2393},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fconsolidate-duplicate-urls?utm_source=chatgpt.com",[50],"Canonical URL documentation",[382,2396,2365,2397,2369,2400],{},[28,2398,2399],{},"What is canonicalization",[46,2401,2404],{"href":2402,"rel":2403},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fcanonicalization?utm_source=chatgpt.com",[50],"Canonicalization overview",[382,2406,2353,2407,2369,2410],{},[28,2408,2409],{},"How HTTP status codes affect Google's crawlers",[46,2411,2414],{"href":2412,"rel":2413},"https:\u002F\u002Fdevelopers.google.com\u002Fcrawling\u002Fdocs\u002Ftroubleshooting\u002Fhttp-status-codes?utm_source=chatgpt.com",[50],"HTTP status code crawling documentation",[382,2416,2365,2417,2369,2420],{},[28,2418,2419],{},"Build and submit a sitemap",[46,2421,2424],{"href":2422,"rel":2423},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fsitemaps\u002Fbuild-sitemap?utm_source=chatgpt.com",[50],"Google sitemap documentation",[382,2426,2353,2427,2369,2430],{},[28,2428,2429],{},"How Google interprets the robots.txt specification",[46,2431,2434],{"href":2432,"rel":2433},"https:\u002F\u002Fdevelopers.google.com\u002Fcrawling\u002Fdocs\u002Frobots-txt\u002Frobots-txt-spec?utm_source=chatgpt.com",[50],"Google robots.txt documentation",{"title":173,"searchDepth":215,"depth":215,"links":2436},[2437,2438,2439,2440,2441,2442,2448,2449,2455,2456,2457,2458],{"id":1857,"depth":215,"text":1858},{"id":1870,"depth":215,"text":1871},{"id":1908,"depth":215,"text":1909},{"id":1986,"depth":215,"text":1987},{"id":2032,"depth":215,"text":2033},{"id":2097,"depth":215,"text":2098,"children":2443},[2444,2445,2446,2447],{"id":2113,"depth":224,"text":2114},{"id":2135,"depth":224,"text":2136},{"id":2147,"depth":224,"text":2148},{"id":2177,"depth":224,"text":2178},{"id":2197,"depth":215,"text":2198},{"id":1629,"depth":215,"text":1630,"children":2450},[2451,2452,2453,2454],{"id":2242,"depth":224,"text":2243},{"id":2249,"depth":224,"text":2250},{"id":2259,"depth":224,"text":2260},{"id":2269,"depth":224,"text":2270},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Learn what crawl budget means, when it matters for SEO, when it does not, and how large websites can reduce wasted Googlebot crawling.","\u002Fcrawl-budget.png","Image of Crawl Budget",{},"\u002Fblog\u002Fen\u002Fcrawl-budget",{"title":1852,"description":2459},"crawl-budget","blog\u002Fen\u002Fcrawl-budget",1685,"RlTu3lfQLxoqtuaMuL0vPf5Umhdlzy0kRw-QzJyRBbQ",{"id":2470,"title":2471,"author":6,"body":2472,"category":1104,"description":3274,"draft":1106,"extension":1107,"featured":280,"image":3275,"imageAlt":3276,"locale":1110,"meta":3277,"navigation":280,"path":3278,"publishedAt":1844,"readingTime":277,"seo":3279,"slug":3280,"stem":3281,"translationKey":3280,"updatedAt":1844,"wordCount":3282,"__hash__":3283},"blog\u002Fblog\u002Fen\u002Finp-explained.md","INP Explained: Interaction to Next Paint Guide",{"type":8,"value":2473,"toc":3250},[2474,2478,2485,2488,2492,2497,2500,2511,2514,2517,2520,2524,2527,2564,2571,2574,2578,2581,2584,2587,2592,2595,2609,2612,2616,2619,2624,2627,2631,2634,2637,2640,2643,2647,2650,2652,2702,2705,2708,2712,2715,2718,2721,2726,2730,2733,2738,2743,2746,2749,2752,2756,2765,2769,2772,2775,2778,2783,2786,2789,2795,2855,2858,2933,2936,2940,2943,2946,2969,2972,2975,2979,2982,2985,2990,2997,3003,3009,3012,3017,3022,3026,3029,3032,3035,3038,3042,3045,3052,3055,3058,3062,3069,3072,3075,3081,3083,3086,3089,3092,3095,3100,3103,3105,3109,3116,3120,3123,3127,3130,3134,3137,3141,3144,3146,3152,3159,3162,3164,3247],[11,2475,2477],{"id":2476},"inp-explained-interaction-to-next-paint","INP Explained: Interaction to Next Paint",[16,2479,2480,2481,2484],{},"A page can load quickly and still feel slow. You click a menu, press “Add to cart,” or type into a search box, but the interface hesitates before anything visible happens. Interaction to Next Paint, or ",[28,2482,2483],{},"INP",", measures this kind of responsiveness.",[16,2486,2487],{},"INP is one of Google’s three Core Web Vitals, alongside Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS). It looks at interactions throughout a user’s visit rather than judging responsiveness from only the first interaction. INP officially replaced First Input Delay (FID) as a Core Web Vital on March 12, 2024.",[11,2489,2491],{"id":2490},"what-is-inp","What Is INP?",[16,2493,2494],{},[28,2495,2496],{},"Interaction to Next Paint measures how long a page takes to provide the next visual frame after a user interaction.",[16,2498,2499],{},"It observes qualifying interactions such as:",[379,2501,2502,2505,2508],{},[382,2503,2504],{},"mouse clicks;",[382,2506,2507],{},"touchscreen taps;",[382,2509,2510],{},"keyboard presses.",[16,2512,2513],{},"For each interaction, INP measures the time from the user beginning the interaction until the browser is able to present the next frame. It therefore measures more than JavaScript execution alone.",[16,2515,2516],{},"Scrolling, hovering, and zooming are not directly included in INP.",[16,2518,2519],{},"A low INP means the page responds consistently quickly. A high INP usually means that at least some important interactions are being delayed by main-thread work, expensive event handlers, rendering work, or a combination of these problems.",[11,2521,2523],{"id":2522},"inp-score-thresholds","INP Score Thresholds",[16,2525,2526],{},"Google and the Chrome team currently classify INP using these thresholds:",[65,2528,2529,2538],{},[68,2530,2531],{},[71,2532,2533,2535],{},[74,2534,2483],{},[74,2536,2537],{},"Rating",[84,2539,2540,2548,2556],{},[71,2541,2542,2545],{},[89,2543,2544],{},"≤ 200 ms",[89,2546,2547],{},"Good",[71,2549,2550,2553],{},[89,2551,2552],{},"> 200 ms to ≤ 500 ms",[89,2554,2555],{},"Needs improvement",[71,2557,2558,2561],{},[89,2559,2560],{},"> 500 ms",[89,2562,2563],{},"Poor",[16,2565,2566,2567,2570],{},"The recommended assessment uses the ",[28,2568,2569],{},"75th percentile of page visits",", considered separately for mobile and desktop users.",[16,2572,2573],{},"This distinction matters. A 150 ms interaction on your development laptop does not prove that users have good INP. Real visitors may have slower CPUs, different browser conditions, more background work, or different interaction patterns.",[11,2575,2577],{"id":2576},"how-inp-works","How INP Works",[16,2579,2580],{},"INP does not calculate an average of every interaction.",[16,2582,2583],{},"Chrome observes interactions across the lifespan of the page and selects a value representing one of the slowest interactions. For most page visits, the worst interaction becomes the INP candidate. On highly interactive pages, the calculation reduces the influence of rare outliers: one highest-latency interaction is ignored for every 50 interactions.",[16,2585,2586],{},"This design answers a useful question:",[16,2588,2589],{},[28,2590,2591],{},"Was the page reliably responsive, even when the user performed many different actions?",[16,2593,2594],{},"Consider a product page:",[1745,2596,2597,2600,2603,2606],{},[382,2598,2599],{},"Opening the navigation takes 70 ms.",[382,2601,2602],{},"Selecting a product option takes 110 ms.",[382,2604,2605],{},"Opening a size selector takes 90 ms.",[382,2607,2608],{},"Clicking “Add to cart” takes 620 ms.",[16,2610,2611],{},"The page may feel fast most of the time, but the important cart interaction is clearly poor. An average could hide that problem. INP is intentionally much more sensitive to these slow experiences.",[11,2613,2615],{"id":2614},"the-three-parts-of-inp","The Three Parts of INP",[16,2617,2618],{},"An interaction can be divided into three main phases:",[16,2620,2621],{},[28,2622,2623],{},"Input delay → Processing duration → Presentation delay",[16,2625,2626],{},"Together, they form the total interaction latency.",[1632,2628,2630],{"id":2629},"input-delay","Input Delay",[16,2632,2633],{},"Input delay is the time between the user initiating an interaction and the browser beginning to execute its event callbacks.",[16,2635,2636],{},"Suppose a user clicks a button while the browser’s main thread is already executing a large JavaScript task. The click has arrived, but the browser cannot immediately process it.",[16,2638,2639],{},"The interaction waits.",[16,2641,2642],{},"Large scripts, long-running tasks, timers, parsing and JavaScript execution can all contribute to this delay.",[1632,2644,2646],{"id":2645},"processing-duration","Processing Duration",[16,2648,2649],{},"Processing duration is the time spent running the event callbacks associated with the interaction.",[16,2651,2065],{},[168,2653,2655],{"className":170,"code":2654,"language":172,"meta":173,"style":173},"button.addEventListener('click', () => {\n    calculateLargeDataset();\n    updateApplicationState();\n    renderResults();\n});\n",[20,2656,2657,2676,2684,2691,2698],{"__ignoreMap":173},[177,2658,2659,2662,2664,2666,2669,2672,2674],{"class":179,"line":180},[177,2660,2661],{"class":183},"button.",[177,2663,188],{"class":187},[177,2665,191],{"class":183},[177,2667,2668],{"class":194},"'click'",[177,2670,2671],{"class":183},", () ",[177,2673,209],{"class":208},[177,2675,212],{"class":183},[177,2677,2678,2681],{"class":179,"line":215},[177,2679,2680],{"class":187},"    calculateLargeDataset",[177,2682,2683],{"class":183},"();\n",[177,2685,2686,2689],{"class":179,"line":224},[177,2687,2688],{"class":187},"    updateApplicationState",[177,2690,2683],{"class":183},[177,2692,2693,2696],{"class":179,"line":235},[177,2694,2695],{"class":187},"    renderResults",[177,2697,2683],{"class":183},[177,2699,2700],{"class":179,"line":241},[177,2701,274],{"class":183},[16,2703,2704],{},"If those operations consume hundreds of milliseconds synchronously, the browser cannot quickly produce visual feedback.",[16,2706,2707],{},"Reducing unnecessary work and breaking large units of work into smaller tasks can help the main thread become available sooner.",[1632,2709,2711],{"id":2710},"presentation-delay","Presentation Delay",[16,2713,2714],{},"Even after event handlers finish, the browser may still need to calculate styles, perform layout, paint, and prepare the next frame.",[16,2716,2717],{},"That time is the presentation delay.",[16,2719,2720],{},"A very large DOM, expensive style recalculation, complex rendering work, or excessive synchronous UI updates can therefore hurt INP even when the event handler itself is not especially slow.",[16,2722,2723],{},[177,2724,2725],{},"INTERNAL LINK: Browser Rendering Pipeline Explained",[11,2727,2729],{"id":2728},"inp-vs-fid","INP vs FID",[16,2731,2732],{},"INP replaced First Input Delay because the two metrics measure responsiveness differently.",[16,2734,2735],{},[28,2736,2737],{},"FID measured only the input delay of the first interaction.",[16,2739,2740],{},[28,2741,2742],{},"INP evaluates interactions across the page visit and includes the path from input through event processing to the next visual frame.",[16,2744,2745],{},"This means a page could historically achieve a good FID while still becoming frustrating later.",[16,2747,2748],{},"For example, the first menu click might respond instantly, giving the page a good FID. Ten seconds later, a complex filtering interface could take 700 ms to respond. FID would never capture that second problem. INP can.",[16,2750,2751],{},"Google replaced FID with INP in Core Web Vitals on March 12, 2024.",[11,2753,2755],{"id":2754},"how-to-measure-inp","How to Measure INP",[16,2757,2758,2759,2165,2762,59],{},"There are two broad measurement approaches: ",[28,2760,2761],{},"field data",[28,2763,2764],{},"lab testing",[1632,2766,2768],{"id":2767},"field-data","Field Data",[16,2770,2771],{},"Field data comes from real users and is the most important place to evaluate INP.",[16,2773,2774],{},"PageSpeed Insights can expose Chrome User Experience Report (CrUX) data when sufficient data is available. Search Console also provides Core Web Vitals reporting.",[16,2776,2777],{},"CrUX is useful for answering:",[1573,2779,2780],{},[16,2781,2782],{},"Do real users have an INP problem?",[16,2784,2785],{},"But aggregate CrUX data often cannot tell you exactly which button, component, script, or interaction caused it.",[16,2787,2788],{},"That is where Real User Monitoring becomes more useful.",[16,2790,2791,2792,2794],{},"Google’s ",[20,2793,432],{}," library can collect INP directly from supported browsers:",[168,2796,2798],{"className":170,"code":2797,"language":172,"meta":173,"style":173},"import {onINP} from 'web-vitals';\n\nonINP(({value, rating}) => {\n    console.log(value, rating);\n});\n",[20,2799,2800,2814,2818,2840,2851],{"__ignoreMap":173},[177,2801,2802,2804,2807,2809,2812],{"class":179,"line":180},[177,2803,447],{"class":208},[177,2805,2806],{"class":183}," {onINP} ",[177,2808,453],{"class":208},[177,2810,2811],{"class":194}," 'web-vitals'",[177,2813,459],{"class":183},[177,2815,2816],{"class":179,"line":215},[177,2817,281],{"emptyLinePlaceholder":280},[177,2819,2820,2822,2825,2828,2830,2833,2836,2838],{"class":179,"line":224},[177,2821,528],{"class":187},[177,2823,2824],{"class":183},"(({",[177,2826,2827],{"class":201},"value",[177,2829,406],{"class":183},[177,2831,2832],{"class":201},"rating",[177,2834,2835],{"class":183},"}) ",[177,2837,209],{"class":208},[177,2839,212],{"class":183},[177,2841,2842,2845,2848],{"class":179,"line":235},[177,2843,2844],{"class":183},"    console.",[177,2846,2847],{"class":187},"log",[177,2849,2850],{"class":183},"(value, rating);\n",[177,2852,2853],{"class":179,"line":241},[177,2854,274],{"class":183},[16,2856,2857],{},"The library also provides an attribution build that can expose diagnostic context about problematic interactions.",[168,2859,2861],{"className":170,"code":2860,"language":172,"meta":173,"style":173},"import {onINP} from 'web-vitals\u002Fattribution';\n\nonINP(({value, rating, attribution}) => {\n    console.log({\n        value,\n        rating,\n        target: attribution.interactionTarget,\n    });\n});\n",[20,2862,2863,2875,2879,2902,2910,2915,2920,2925,2929],{"__ignoreMap":173},[177,2864,2865,2867,2869,2871,2873],{"class":179,"line":180},[177,2866,447],{"class":208},[177,2868,2806],{"class":183},[177,2870,453],{"class":208},[177,2872,456],{"class":194},[177,2874,459],{"class":183},[177,2876,2877],{"class":179,"line":215},[177,2878,281],{"emptyLinePlaceholder":280},[177,2880,2881,2883,2885,2887,2889,2891,2893,2896,2898,2900],{"class":179,"line":224},[177,2882,528],{"class":187},[177,2884,2824],{"class":183},[177,2886,2827],{"class":201},[177,2888,406],{"class":183},[177,2890,2832],{"class":201},[177,2892,406],{"class":183},[177,2894,2895],{"class":201},"attribution",[177,2897,2835],{"class":183},[177,2899,209],{"class":208},[177,2901,212],{"class":183},[177,2903,2904,2906,2908],{"class":179,"line":235},[177,2905,2844],{"class":183},[177,2907,2847],{"class":187},[177,2909,221],{"class":183},[177,2911,2912],{"class":179,"line":241},[177,2913,2914],{"class":183},"        value,\n",[177,2916,2917],{"class":179,"line":247},[177,2918,2919],{"class":183},"        rating,\n",[177,2921,2922],{"class":179,"line":253},[177,2923,2924],{"class":183},"        target: attribution.interactionTarget,\n",[177,2926,2927],{"class":179,"line":259},[177,2928,268],{"class":183},[177,2930,2931],{"class":179,"line":265},[177,2932,274],{"class":183},[16,2934,2935],{},"For production monitoring, this information should normally be sent to an analytics or observability system rather than only logged to the console.",[1632,2937,2939],{"id":2938},"lab-testing","Lab Testing",[16,2941,2942],{},"Lab testing helps reproduce and investigate slow interactions after they have been identified.",[16,2944,2945],{},"Test realistic actions such as:",[379,2947,2948,2951,2954,2957,2960,2963,2966],{},[382,2949,2950],{},"opening navigation;",[382,2952,2953],{},"changing filters;",[382,2955,2956],{},"expanding accordions;",[382,2958,2959],{},"typing into search;",[382,2961,2962],{},"submitting forms;",[382,2964,2965],{},"switching tabs;",[382,2967,2968],{},"adding products to a cart.",[16,2970,2971],{},"Testing during page load is also useful because JavaScript parsing, compilation, and execution can make the main thread especially busy at that point.",[16,2973,2974],{},"However, a lab INP result depends on which interactions you perform. A test that never triggers the problematic interaction may completely miss the real issue.",[11,2976,2978],{"id":2977},"how-to-improve-inp","How to Improve INP",[16,2980,2981],{},"Start by finding the slow interaction, then identify which part of its latency is responsible.",[16,2983,2984],{},"A useful diagnostic flow is:",[16,2986,2987],{},[28,2988,2989],{},"Slow INP → identify interaction → inspect phase → confirm cause → optimize → measure again",[16,2991,2992,2993,2996],{},"If ",[28,2994,2995],{},"input delay"," is high, investigate long tasks and excessive JavaScript running before the event handler gets a chance to execute.",[16,2998,2992,2999,3002],{},[28,3000,3001],{},"processing duration"," is high, inspect the event callback itself. Remove unnecessary synchronous work, simplify computation, and split long work when possible.",[16,3004,2992,3005,3008],{},[28,3006,3007],{},"presentation delay"," is high, investigate rendering costs such as style recalculation, layout, DOM complexity, and expensive visual updates.",[16,3010,3011],{},"Do not begin by randomly deleting JavaScript or changing framework configuration. INP is the outcome of several phases, so optimization should target the phase that is actually slow.",[16,3013,3014],{},[177,3015,3016],{},"INTERNAL LINK: Long Tasks and Main Thread Performance",[16,3018,3019],{},[177,3020,3021],{},"INTERNAL LINK: How DOM Size Affects Web Performance",[11,3023,3025],{"id":3024},"common-inp-mistakes","Common INP Mistakes",[16,3027,3028],{},"One common mistake is testing only page load. INP measures responsiveness throughout the visit, so a page can load perfectly and still have poor interactions later.",[16,3030,3031],{},"Another is treating Total Blocking Time as INP. TBT can help identify main-thread blocking in lab tests, but web.dev explicitly describes it as a possible proxy in some situations, not a replacement for real INP measurement.",[16,3033,3034],{},"A third mistake is assuming every slow interaction is caused by the network. INP primarily concerns the period until the next frame can be shown. A later asynchronous API response is not automatically part of the original interaction’s INP duration.",[16,3036,3037],{},"Finally, a good local result does not guarantee a good field result. Production users run your site on a much wider range of devices and conditions.",[11,3039,3041],{"id":3040},"inp-and-seo","INP and SEO",[16,3043,3044],{},"INP is a Core Web Vital, and Google Search Central says Core Web Vitals measure real-world loading performance, interactivity, and visual stability. Google recommends achieving good Core Web Vitals both for user experience and for success with Search.",[16,3046,3047,3048,3051],{},"That does ",[28,3049,3050],{},"not"," mean improving INP guarantees a ranking increase.",[16,3053,3054],{},"Google explicitly frames page experience as one part of a broader set of signals. Relevant, helpful content can still rank when page experience is imperfect, and good Core Web Vitals alone do not guarantee high rankings.",[16,3056,3057],{},"The safer conclusion is practical: improve INP because it improves responsiveness for users and because Core Web Vitals are relevant to Google’s understanding of page experience—not because a particular millisecond improvement can be translated into a predictable ranking gain.",[11,3059,3061],{"id":3060},"inp-edge-cases","INP Edge Cases",[16,3063,3064,3065,3068],{},"A page may have ",[28,3066,3067],{},"no INP value at all"," if the visitor never clicks, taps, or presses a key. Users who only scroll or hover may also generate no qualifying interaction.",[16,3070,3071],{},"Embedded content introduces another measurement complication. INP at the page level can include interactions inside iframes, while JavaScript running in the top-level document may not have access to interaction timing from cross-origin frames. This can produce differences between CrUX data and your own RUM measurements.",[16,3073,3074],{},"The underlying Event Timing API also has implementation details developers should be aware of. For example, its default buffering threshold is 104 ms, although observers can request a lower threshold subject to API limits.",[16,3076,3077,3078,3080],{},"For most teams, using the maintained ",[20,3079,432],{}," implementation is safer than rebuilding the complete INP calculation manually.",[11,3082,899],{"id":898},[16,3084,3085],{},"Treat INP as an interaction-level observability problem, not merely a score in PageSpeed Insights.",[16,3087,3088],{},"Start with real-user data. Identify which pages and user flows perform poorly. Then collect attribution data to determine which interactions are responsible. Reproduce those interactions under realistic device conditions and separate their latency into input delay, processing duration, and presentation delay.",[16,3090,3091],{},"Only then optimize.",[16,3093,3094],{},"This approach turns a vague report such as “INP is 480 ms” into an engineering problem you can act on:",[16,3096,3097],{},[28,3098,3099],{},"Search filter click → 480 ms → 45 ms input delay + 310 ms processing + 125 ms presentation delay → expensive synchronous filtering and DOM update.",[16,3101,3102],{},"That level of attribution is much more useful than chasing a green performance score.",[11,3104,919],{"id":918},[921,3106,3108],{"id":3107},"what-is-a-good-inp","What is a good INP?",[16,3110,3111,3112,3115],{},"An INP of ",[28,3113,3114],{},"200 ms or less"," is considered good. Between 200 and 500 ms needs improvement, while values above 500 ms are considered poor. The recommended site assessment uses the 75th percentile of page visits.",[921,3117,3119],{"id":3118},"does-inp-measure-page-loading-speed","Does INP measure page loading speed?",[16,3121,3122],{},"No. INP measures responsiveness to user interactions. LCP is the Core Web Vital specifically focused on loading performance.",[921,3124,3126],{"id":3125},"does-scrolling-affect-inp","Does scrolling affect INP?",[16,3128,3129],{},"Scrolling itself is not one of the interaction types used for INP. Clicks, taps, and keyboard interactions are measured.",[921,3131,3133],{"id":3132},"is-inp-a-google-ranking-factor","Is INP a Google ranking factor?",[16,3135,3136],{},"INP is a Core Web Vital and Core Web Vitals are part of Google’s broader page-experience considerations. However, Google does not document a simple rule such as “improving INP by X milliseconds increases rankings by Y.” Good Core Web Vitals also do not guarantee rankings.",[921,3138,3140],{"id":3139},"why-does-pagespeed-insights-show-no-inp","Why does PageSpeed Insights show no INP?",[16,3142,3143],{},"There may not be enough qualifying real-user interaction data for the URL or origin. A particular page visit can also have no INP when the user never performs a qualifying interaction.",[11,3145,952],{"id":951},[16,3147,3148,3149],{},"INP answers a simple but important question: ",[28,3150,3151],{},"when a user tries to do something, how quickly does the page visibly respond?",[16,3153,3154,3155,3158],{},"Unlike FID, it evaluates responsiveness across the visit and follows an interaction through input delay, event processing, and the browser’s next paint. Aim for ",[28,3156,3157],{},"200 ms or less at the 75th percentile",", but do not optimize the number blindly.",[16,3160,3161],{},"Find the slow interaction, determine where its latency comes from, fix that specific bottleneck, and measure real users again.",[11,3163,980],{"id":979},[1745,3165,3166,3176,3186,3196,3206,3216,3226,3237],{},[382,3167,3168,3171],{},[28,3169,3170],{},"web.dev — Jeremy Wagner and Barry Pollard, “Interaction to Next Paint (INP),” published May 6, 2022; updated September 2, 2025.",[46,3172,3175],{"href":3173,"rel":3174},"https:\u002F\u002Fweb.dev\u002Farticles\u002Finp?utm_source=chatgpt.com",[50],"Interaction to Next Paint — web.dev",[382,3177,3178,3181],{},[28,3179,3180],{},"web.dev — Jeremy Wagner, Philip Walton and Barry Pollard, “Optimize Interaction to Next Paint,” published May 19, 2023; updated September 2, 2025.",[46,3182,3185],{"href":3183,"rel":3184},"https:\u002F\u002Fweb.dev\u002Farticles\u002Foptimize-inp?utm_source=chatgpt.com",[50],"Optimize Interaction to Next Paint — web.dev",[382,3187,3188,3191],{},[28,3189,3190],{},"Google Search Central — “Understanding Core Web Vitals and Google search results,” updated December 10, 2025.",[46,3192,3195],{"href":3193,"rel":3194},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fcore-web-vitals?utm_source=chatgpt.com",[50],"Core Web Vitals and Google Search",[382,3197,3198,3201],{},[28,3199,3200],{},"Google Search Central — Martin Splitt, “Introducing INP to Core Web Vitals,” May 10, 2023; updated March 12, 2024.",[46,3202,3205],{"href":3203,"rel":3204},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fblog\u002F2023\u002F05\u002Fintroducing-inp?utm_source=chatgpt.com",[50],"Introducing INP to Core Web Vitals",[382,3207,3208,3211],{},[28,3209,3210],{},"W3C Web Performance Working Group — Event Timing API specification.",[46,3212,3215],{"href":3213,"rel":3214},"https:\u002F\u002Fw3c.github.io\u002Fevent-timing\u002F?utm_source=chatgpt.com",[50],"Event Timing API specification",[382,3217,3218,3221],{},[28,3219,3220],{},"web.dev — “Find slow interactions in the field.”",[46,3222,3225],{"href":3223,"rel":3224},"https:\u002F\u002Fweb.dev\u002Farticles\u002Ffind-slow-interactions-in-the-field?utm_source=chatgpt.com",[50],"Find slow interactions in the field",[382,3227,3228,3233],{},[28,3229,1025,3230,3232],{},[20,3231,432],{}," JavaScript library and reference implementation.",[46,3234,3236],{"href":1031,"rel":3235},[50],"GoogleChrome web-vitals repository",[382,3238,3239,3242],{},[28,3240,3241],{},"web.dev — “Advancing Interaction to Next Paint.”",[46,3243,3246],{"href":3244,"rel":3245},"https:\u002F\u002Fweb.dev\u002Fblog\u002Finp-cwv?utm_source=chatgpt.com",[50],"Advancing Interaction to Next Paint",[1086,3248,3249],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":173,"searchDepth":215,"depth":215,"links":3251},[3252,3253,3254,3255,3256,3261,3262,3266,3267,3268,3269,3270,3271,3272,3273],{"id":2476,"depth":215,"text":2477},{"id":2490,"depth":215,"text":2491},{"id":2522,"depth":215,"text":2523},{"id":2576,"depth":215,"text":2577},{"id":2614,"depth":215,"text":2615,"children":3257},[3258,3259,3260],{"id":2629,"depth":224,"text":2630},{"id":2645,"depth":224,"text":2646},{"id":2710,"depth":224,"text":2711},{"id":2728,"depth":215,"text":2729},{"id":2754,"depth":215,"text":2755,"children":3263},[3264,3265],{"id":2767,"depth":224,"text":2768},{"id":2938,"depth":224,"text":2939},{"id":2977,"depth":215,"text":2978},{"id":3024,"depth":215,"text":3025},{"id":3040,"depth":215,"text":3041},{"id":3060,"depth":215,"text":3061},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Learn what Interaction to Next Paint (INP) measures, what a good INP score is, how it works, how to diagnose slow interactions, and how to improve responsiveness.","\u002Finp.png","INP Explained",{},"\u002Fblog\u002Fen\u002Finp-explained",{"title":2471,"description":3274},"inp-explained","blog\u002Fen\u002Finp-explained",2053,"3yvzJKph16_yg8g9Si_9JMmImez_ygF6suOoeXB3XdI",{"id":3285,"title":3286,"author":6,"body":3287,"category":1104,"description":3945,"draft":1106,"extension":1107,"featured":280,"image":3946,"imageAlt":3947,"locale":1110,"meta":3948,"navigation":280,"path":3949,"publishedAt":1113,"readingTime":271,"seo":3950,"slug":3951,"stem":3952,"translationKey":3951,"updatedAt":1113,"wordCount":3953,"__hash__":3954},"blog\u002Fblog\u002Fen\u002Fbackend-observability.md","Backend Observability: Requests, Queries, Queues & Dependencies",{"type":8,"value":3288,"toc":3929},[3289,3293,3299,3309,3311,3314,3319,3326,3336,3340,3401,3413,3417,3420,3423,3443,3449,3456,3461,3465,3472,3475,3481,3484,3491,3494,3506,3521,3526,3530,3533,3536,3542,3545,3548,3563,3570,3577,3582,3586,3589,3595,3598,3601,3607,3610,3616,3619,3623,3626,3643,3646,3652,3663,3666,3670,3673,3676,3679,3685,3688,3691,3694,3699,3702,3706,3713,3723,3730,3737,3740,3742,3745,3748,3751,3756,3759,3761,3765,3768,3772,3775,3779,3782,3786,3789,3793,3799,3801,3804,3810,3813,3816,3818],[11,3290,3292],{"id":3291},"backend-observability-requests-queries-queues-and-dependencies","Backend Observability: Requests, Queries, Queues, and Dependencies",[16,3294,3295,3296,3298],{},"A backend can return ",[20,3297,22],{}," and still be unhealthy. Requests may be slowing down, database calls may be multiplying, jobs may be waiting in a queue, or an external API may be consuming most of the response time. CPU and memory graphs alone rarely explain these failures.",[16,3300,3301,3302,3305,3306,59],{},"Backend observability means collecting enough signals to understand ",[28,3303,3304],{},"what a backend is doing, where time is being spent, what is failing, and why",". For most application backends, four areas provide a useful starting model: ",[28,3307,3308],{},"requests, database queries, queues, and dependencies",[11,3310,41],{"id":40},[16,3312,3313],{},"Backend observability should let you follow work through the system:",[16,3315,3316],{},[28,3317,3318],{},"request → application code → database → queue → worker → downstream dependency",[16,3320,3321,3322,52],{},"Metrics show patterns such as rising latency or error rates. Traces connect operations across components. Logs provide detailed events and context. OpenTelemetry supports correlation between these signals through trace and span identifiers, while W3C Trace Context defines a standard mechanism for propagating tracing information between services. (",[46,3323,51],{"href":3324,"rel":3325},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fspecs\u002Fotel\u002Flogs\u002F?utm_source=chatgpt.com",[50],[16,3327,3328,3329,3332,3333],{},"The goal is not to collect everything. It is to collect enough evidence that an engineer can move from ",[28,3330,3331],{},"“the API is slow”"," to ",[28,3334,3335],{},"“this endpoint is waiting on this query, queue, or dependency.”",[11,3337,3339],{"id":3338},"what-should-you-observe","What Should You Observe?",[65,3341,3342,3355],{},[68,3343,3344],{},[71,3345,3346,3349,3352],{},[74,3347,3348],{},"Area",[74,3350,3351],{},"Useful signals",[74,3353,3354],{},"Questions answered",[84,3356,3357,3368,3379,3390],{},[71,3358,3359,3362,3365],{},[89,3360,3361],{},"Requests",[89,3363,3364],{},"rate, latency distribution, status, errors",[89,3366,3367],{},"Which endpoints are slow or failing?",[71,3369,3370,3373,3376],{},[89,3371,3372],{},"Queries",[89,3374,3375],{},"duration, query pattern, calls, errors",[89,3377,3378],{},"Is the database causing the delay?",[71,3380,3381,3384,3387],{},[89,3382,3383],{},"Queues",[89,3385,3386],{},"depth, wait time, processing time, failures",[89,3388,3389],{},"Is asynchronous work falling behind?",[71,3391,3392,3395,3398],{},[89,3393,3394],{},"Dependencies",[89,3396,3397],{},"latency, errors, timeouts",[89,3399,3400],{},"Is another service responsible?",[16,3402,3403,3404,3407,3408,52],{},"This model complements broader service monitoring. Google’s SRE guidance describes ",[28,3405,3406],{},"latency, traffic, errors, and saturation"," as four fundamental monitoring signals for user-facing systems. (",[46,3409,3412],{"href":3410,"rel":3411},"https:\u002F\u002Fsre.google\u002Fsre-book\u002Fmonitoring-distributed-systems\u002F?utm_source=chatgpt.com",[50],"sre.google",[11,3414,3416],{"id":3415},"start-with-requests","Start With Requests",[16,3418,3419],{},"Requests are usually the best entry point because they represent work that users or other systems actually asked the backend to perform.",[16,3421,3422],{},"For an HTTP API, useful measurements include:",[379,3424,3425,3428,3431,3434,3437,3440],{},[382,3426,3427],{},"requests per second;",[382,3429,3430],{},"response status or application outcome;",[382,3432,3433],{},"request duration;",[382,3435,3436],{},"latency distribution such as p50, p95, or p99;",[382,3438,3439],{},"route or operation;",[382,3441,3442],{},"service and deployment version.",[16,3444,3445,3446,52],{},"Do not rely only on average response time. A service can have a reasonable average while a smaller percentage of requests are extremely slow. Google SRE specifically warns about latency tails, and histogram-style measurements make those distributions visible. Prometheus also documents histograms as a mechanism for representing distributions such as request duration. (",[46,3447,3412],{"href":3410,"rel":3448},[50],[16,3450,3451,3452,52],{},"OpenTelemetry defines standard semantic conventions for HTTP client and server spans. Using consistent attributes and operation names makes traces easier to compare across frameworks and services. (",[46,3453,51],{"href":3454,"rel":3455},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fspecs\u002Fsemconv\u002Fhttp\u002Fhttp-spans\u002F?utm_source=chatgpt.com",[50],[16,3457,3458],{},[177,3459,3460],{},"INTERNAL LINK: HTTP Request Performance Monitoring",[11,3462,3464],{"id":3463},"follow-the-queries","Follow the Queries",[16,3466,3467,3468,3471],{},"Suppose ",[20,3469,3470],{},"\u002Fapi\u002Fproducts"," becomes slow.",[16,3473,3474],{},"The request itself tells you that a problem exists, but not necessarily why. A trace might show something like:",[168,3476,3479],{"className":3477,"code":3478,"language":787,"meta":173},[785],"GET \u002Fapi\u002Fproducts             680 ms\n├── authentication             12 ms\n├── SELECT products           610 ms\n└── response serialization     18 ms\n",[20,3480,3478],{"__ignoreMap":173},[16,3482,3483],{},"Now the investigation has changed. Instead of optimizing the controller, you investigate the database operation.",[16,3485,3486,3487,52],{},"OpenTelemetry defines database client spans for representing database operations observed by the calling application. (",[46,3488,51],{"href":3489,"rel":3490},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fspecs\u002Fsemconv\u002Fdb\u002Fdatabase-spans\u002F?utm_source=chatgpt.com",[50],[16,3492,3493],{},"Useful database signals include query duration, call frequency, errors, connection-pool pressure, and a normalized query identity. Recording every literal SQL statement is not always appropriate: query text may contain sensitive or high-cardinality values, so instrumentation should follow the sanitization and data-handling rules of the database and observability stack.",[16,3495,3496,3497,3500,3501,52],{},"For PostgreSQL, ",[20,3498,3499],{},"pg_stat_statements"," can aggregate planning and execution statistics for SQL statements, making it useful for identifying expensive or frequently executed query patterns. (",[46,3502,3505],{"href":3503,"rel":3504},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002F19\u002Fpgstatstatements.html?utm_source=chatgpt.com",[50],"postgresql.org",[16,3507,3508,3509,3512,3513,3516,3517,52],{},"Once a suspicious query is identified, ",[20,3510,3511],{},"EXPLAIN"," shows the execution plan. ",[20,3514,3515],{},"EXPLAIN ANALYZE"," actually executes the query and reports real row counts and execution timing for plan nodes, which can help verify whether estimates, scans, joins, or other operations are responsible for the observed behavior. (",[46,3518,3505],{"href":3519,"rel":3520},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002F18\u002Fusing-explain.html?utm_source=chatgpt.com",[50],[16,3522,3523],{},[177,3524,3525],{},"INTERNAL LINK: Diagnosing Slow SQL Queries",[11,3527,3529],{"id":3528},"observe-queue-time-separately","Observe Queue Time Separately",[16,3531,3532],{},"Queues change the meaning of latency.",[16,3534,3535],{},"Consider an image-processing job:",[168,3537,3540],{"className":3538,"code":3539,"language":787,"meta":173},[785],"created\n   ↓\nwaiting in queue: 14.2 s\n   ↓\nworker starts\n   ↓\nprocessing: 820 ms\n   ↓\ncompleted\n",[20,3541,3539],{"__ignoreMap":173},[16,3543,3544],{},"Looking only at worker execution would suggest an 820 ms operation. From the application's perspective, however, the job took more than 15 seconds to complete.",[16,3546,3547],{},"That distinction matters.",[16,3549,3550,3551,406,3554,406,3557,410,3559,3562],{},"Track at least the ",[28,3552,3553],{},"amount of waiting work",[28,3555,3556],{},"time spent waiting",[28,3558,3001],{},[28,3560,3561],{},"failure or retry behavior"," where the queue technology exposes those signals. Queue depth alone can be misleading: ten lightweight jobs and ten expensive jobs do not necessarily represent the same workload.",[16,3564,3565,3566,52],{},"Google SRE describes excessive queue length as both a latency and resource problem: queued requests consume resources and can amplify overload when work arrives faster than the system can process it. (",[46,3567,3412],{"href":3568,"rel":3569},"https:\u002F\u002Fsre.google\u002Fsre-book\u002Faddressing-cascading-failures\u002F?utm_source=chatgpt.com",[50],[16,3571,3572,3573,52],{},"Distributed tracing also becomes harder around asynchronous systems because the producer and consumer execute at different times. OpenTelemetry’s messaging conventions explicitly address propagation between producers and consumers so that operations can still be correlated across messaging infrastructure. (",[46,3574,51],{"href":3575,"rel":3576},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fspecs\u002Fsemconv\u002Fmessaging\u002Fmessaging-spans\u002F?utm_source=chatgpt.com",[50],[16,3578,3579],{},[177,3580,3581],{},"INTERNAL LINK: Queue Monitoring and Worker Performance",[11,3583,3585],{"id":3584},"measure-dependencies","Measure Dependencies",[16,3587,3588],{},"Most production backends do not work alone. A request might depend on:",[168,3590,3593],{"className":3591,"code":3592,"language":787,"meta":173},[785],"Application\n├── PostgreSQL\n├── Redis\n├── payment API\n├── object storage\n└── internal user service\n",[20,3594,3592],{"__ignoreMap":173},[16,3596,3597],{},"A dependency should therefore be observable as a distinct operation rather than disappearing inside total request duration.",[16,3599,3600],{},"For each important dependency, useful signals usually include latency, request volume, error rate, timeout behavior, and the calling operation. This allows an engineer to distinguish two very different situations:",[168,3602,3605],{"className":3603,"code":3604,"language":787,"meta":173},[785],"API slow\n└── application code slow\n",[20,3606,3604],{"__ignoreMap":173},[16,3608,3609],{},"from:",[168,3611,3614],{"className":3612,"code":3613,"language":787,"meta":173},[785],"API slow\n└── payment provider: 2.4 s\n",[20,3615,3613],{"__ignoreMap":173},[16,3617,3618],{},"That difference determines where the investigation should continue.",[11,3620,3622],{"id":3621},"connect-the-entire-trace","Connect the Entire Trace",[16,3624,3625],{},"Distributed observability becomes much more useful when the same operation can be followed across service boundaries.",[16,3627,3628,3629,2165,3632,3635,3636,3638,3639,52],{},"W3C Trace Context defines the ",[20,3630,3631],{},"traceparent",[20,3633,3634],{},"tracestate"," HTTP headers for this purpose. ",[20,3637,3631],{}," carries standardized trace information, allowing cooperating systems to preserve the relationship between operations even when different tracing implementations are involved. (",[46,3640,571],{"href":3641,"rel":3642},"https:\u002F\u002Fwww.w3.org\u002FTR\u002Ftrace-context\u002F?utm_source=chatgpt.com",[50],[16,3644,3645],{},"Conceptually:",[168,3647,3650],{"className":3648,"code":3649,"language":787,"meta":173},[785],"Browser\n   │\n   ▼\nAPI Gateway\ntrace-id: abc\n   │\n   ▼\nOrder Service\ntrace-id: abc\n   │\n   ├── PostgreSQL\n   │     trace-id: abc\n   │\n   └── Payment Service\n         trace-id: abc\n",[20,3651,3649],{"__ignoreMap":173},[16,3653,3654,3655,3658,3659,52],{},"OpenTelemetry calls this ",[28,3656,3657],{},"context propagation",". A downstream service receives the trace context and creates its own span as part of the same distributed trace. (",[46,3660,51],{"href":3661,"rel":3662},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002Fconcepts\u002Fcontext-propagation\u002F?utm_source=chatgpt.com",[50],[16,3664,3665],{},"Without propagation, engineers see isolated operations. With propagation, they see a causal path.",[11,3667,3669],{"id":3668},"a-practical-diagnostic-flow","A Practical Diagnostic Flow",[16,3671,3672],{},"Imagine customers report that checkout occasionally takes five seconds.",[16,3674,3675],{},"Start with the request metric. Confirm whether checkout latency actually increased and whether the problem affects all requests or primarily the slow tail.",[16,3677,3678],{},"Then open a slow trace:",[168,3680,3683],{"className":3681,"code":3682,"language":787,"meta":173},[785],"POST \u002Fcheckout               5.1 s\n├── validate cart             8 ms\n├── SELECT inventory         31 ms\n├── payment request           4.8 s\n└── create order             76 ms\n",[20,3684,3682],{"__ignoreMap":173},[16,3686,3687],{},"The database is probably not the first place to investigate. The payment dependency dominates the trace.",[16,3689,3690],{},"Check dependency metrics and logs for the same period. Look for increased remote latency, timeouts, retries, or connection failures. After making a change, measure the same request and dependency signals again.",[16,3692,3693],{},"The workflow is:",[16,3695,3696],{},[28,3697,3698],{},"symptom → measurement → suspected component → confirmation → fix → re-measurement",[16,3700,3701],{},"That is much more reliable than optimizing whichever component happens to look suspicious first.",[11,3703,3705],{"id":3704},"common-observability-mistakes","Common Observability Mistakes",[16,3707,3708,3709,3712],{},"The first mistake is ",[28,3710,3711],{},"collecting infrastructure metrics without application context",". CPU usage can reveal saturation, but it cannot tell you which endpoint or query caused it.",[16,3714,3715,3716,3719,3720,52],{},"The second is ",[28,3717,3718],{},"logging everything while correlating nothing",". A million log records are difficult to investigate if they cannot be connected to the request or job that generated them. OpenTelemetry supports attaching trace and span identifiers to log records specifically to enable this correlation. (",[46,3721,51],{"href":3324,"rel":3722},[50],[16,3724,3725,3726,3729],{},"The third is ",[28,3727,3728],{},"ignoring asynchronous waiting time",". Worker processing time and end-to-end job latency are different measurements.",[16,3731,3732,3733,3736],{},"The fourth is ",[28,3734,3735],{},"using averages as the entire latency story",". Tail latency may reveal problems hidden by an acceptable mean.",[16,3738,3739],{},"Finally, avoid uncontrolled telemetry cardinality. User IDs, full URLs with arbitrary parameters, raw SQL values, request bodies, or unique job IDs can make metric systems expensive and may expose sensitive data. Keep high-cardinality diagnostic context in systems designed to handle it rather than blindly turning every value into a metric label.",[11,3741,899],{"id":898},[16,3743,3744],{},"Start from the request boundary and instrument outward.",[16,3746,3747],{},"For each critical backend operation, establish request latency, traffic, and errors first. Then expose database calls, messaging operations, and important downstream dependencies as traceable operations. Preserve trace context across HTTP calls and asynchronous messages, and correlate logs with the same execution context.",[16,3749,3750],{},"Do not begin by building dozens of dashboards. Begin with a smaller question:",[16,3752,3753],{},[28,3754,3755],{},"Can an engineer take one slow or failed request and determine where the time or failure came from?",[16,3757,3758],{},"If the answer is no, the backend is still missing important observability.",[11,3760,919],{"id":918},[921,3762,3764],{"id":3763},"are-logs-enough","Are logs enough?",[16,3766,3767],{},"Usually not. Logs provide detailed events, but metrics are better for detecting aggregate patterns, while traces show how operations relate across a request. Correlating all three is more useful than treating them as isolated datasets.",[921,3769,3771],{"id":3770},"should-every-sql-query-become-a-trace-span","Should every SQL query become a trace span?",[16,3773,3774],{},"Useful database operations should be observable, but instrumentation volume, sensitive query data, and telemetry cost matter. Automatic instrumentation should be configured deliberately rather than assumed to be safe at unlimited volume.",[921,3776,3778],{"id":3777},"what-should-i-monitor-for-queues","What should I monitor for queues?",[16,3780,3781],{},"Queue or backlog size, time spent waiting, processing duration, failures, retries, and worker capacity are useful starting points. The exact signals depend on the messaging system and workload.",[921,3783,3785],{"id":3784},"what-is-the-difference-between-monitoring-and-observability","What is the difference between monitoring and observability?",[16,3787,3788],{},"Monitoring commonly tracks predefined system signals and conditions. Observability uses telemetry such as metrics, traces, and logs to investigate system behavior, including failures that were not predicted when dashboards or alerts were created.",[921,3790,3792],{"id":3791},"does-distributed-tracing-require-opentelemetry","Does distributed tracing require OpenTelemetry?",[16,3794,3795,3796,52],{},"No. W3C Trace Context is vendor-neutral, and different tracing implementations can support distributed context propagation. OpenTelemetry provides widely adopted APIs, SDKs, semantic conventions, and tooling for producing and transporting telemetry. (",[46,3797,571],{"href":3641,"rel":3798},[50],[11,3800,952],{"id":951},[16,3802,3803],{},"Good backend observability turns latency from a vague symptom into a sequence of measurable operations.",[16,3805,3806,3807],{},"Do not stop at ",[28,3808,3809],{},"“the request took two seconds.”",[16,3811,3812],{},"Determine whether those two seconds were spent executing application code, waiting for SQL, sitting in a queue, or calling another service. Requests reveal the symptom; queries, queues, and dependencies reveal where the work went; traces and correlated logs connect the evidence.",[16,3814,3815],{},"That is the difference between knowing that a backend is unhealthy and being able to explain why.",[11,3817,980],{"id":979},[1745,3819,3820,3835,3845,3854,3863,3878,3888,3898,3909],{},[382,3821,3822,3825,3826,2165,3828,3830,3831],{},[28,3823,3824],{},"W3C — Trace Context",". W3C Recommendation. Defines standardized ",[20,3827,3631],{},[20,3829,3634],{}," propagation. ",[46,3832,3834],{"href":3641,"rel":3833},[50],"W3C Trace Context",[382,3836,3837,3840,3841],{},[28,3838,3839],{},"OpenTelemetry — Semantic Conventions for HTTP Spans",". Official OpenTelemetry specification. ",[46,3842,3844],{"href":3454,"rel":3843},[50],"OpenTelemetry HTTP Spans",[382,3846,3847,3840,3850],{},[28,3848,3849],{},"OpenTelemetry — Semantic Conventions for Database Client Spans",[46,3851,3853],{"href":3489,"rel":3852},[50],"OpenTelemetry Database Spans",[382,3855,3856,3840,3859],{},[28,3857,3858],{},"OpenTelemetry — Semantic Conventions for Messaging Spans",[46,3860,3862],{"href":3575,"rel":3861},[50],"OpenTelemetry Messaging Spans",[382,3864,3865,3868,3869,3873,3874],{},[28,3866,3867],{},"OpenTelemetry — Context Propagation and Logging Specification",". Official documentation covering distributed context and log correlation. ",[46,3870,3872],{"href":3661,"rel":3871},[50],"OpenTelemetry Context Propagation"," ",[46,3875,3877],{"href":3324,"rel":3876},[50],"OpenTelemetry Logging",[382,3879,3880,3883,3884],{},[28,3881,3882],{},"Google — Site Reliability Engineering: Monitoring Distributed Systems",". Rob Ewaschuk, edited by Betsy Beyer. Covers latency, traffic, errors, saturation, and tail latency. ",[46,3885,3887],{"href":3410,"rel":3886},[50],"Google SRE — Monitoring Distributed Systems",[382,3889,3890,3893,3894],{},[28,3891,3892],{},"Google — Site Reliability Engineering: Addressing Cascading Failures",". Covers queueing, overload, latency, and saturation behavior. ",[46,3895,3897],{"href":3568,"rel":3896},[50],"Google SRE — Addressing Cascading Failures",[382,3899,3900,3903,3904],{},[28,3901,3902],{},"Prometheus — Histograms and Summaries",". Official documentation on representing distributions such as request latency. ",[46,3905,3908],{"href":3906,"rel":3907},"https:\u002F\u002Fprometheus.io\u002Fdocs\u002Fpractices\u002Fhistograms\u002F?utm_source=chatgpt.com",[50],"Prometheus Histograms and Summaries",[382,3910,3911,3919,3920,3873,3925],{},[28,3912,3913,3914,3916,3917],{},"PostgreSQL — ",[20,3915,3499],{}," and Using ",[20,3918,3511],{},". Official PostgreSQL documentation for query statistics and execution-plan analysis. ",[46,3921,3924],{"href":3922,"rel":3923},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002F18\u002Fpgstatstatements.html?utm_source=chatgpt.com",[50],"PostgreSQL pg_stat_statements",[46,3926,3928],{"href":3519,"rel":3927},[50],"PostgreSQL Using EXPLAIN",{"title":173,"searchDepth":215,"depth":215,"links":3930},[3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944],{"id":3291,"depth":215,"text":3292},{"id":40,"depth":215,"text":41},{"id":3338,"depth":215,"text":3339},{"id":3415,"depth":215,"text":3416},{"id":3463,"depth":215,"text":3464},{"id":3528,"depth":215,"text":3529},{"id":3584,"depth":215,"text":3585},{"id":3621,"depth":215,"text":3622},{"id":3668,"depth":215,"text":3669},{"id":3704,"depth":215,"text":3705},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Learn how backend observability connects requests, database queries, queues, dependencies, metrics, traces, and logs to diagnose performance and failures.","\u002Fbackend-observability.png","Image of Backend",{},"\u002Fblog\u002Fen\u002Fbackend-observability",{"title":3286,"description":3945},"backend-observability","blog\u002Fen\u002Fbackend-observability",1801,"aI9b_IbiwH6DGY2SmQJKB4dgY9sQcUZguEj4ulMW194",{"id":3956,"title":3957,"author":6,"body":3958,"category":4955,"description":4956,"draft":1106,"extension":1107,"featured":280,"image":4957,"imageAlt":4958,"locale":1110,"meta":4959,"navigation":280,"path":4960,"publishedAt":4961,"readingTime":271,"seo":4962,"slug":4963,"stem":4964,"translationKey":4963,"updatedAt":4961,"wordCount":4965,"__hash__":4966},"blog\u002Fblog\u002Fen\u002Fcls-explained.md","CLS Explained: What Cumulative Layout Shift Means",{"type":8,"value":3959,"toc":4930},[3960,3964,3971,3978,3982,3987,3997,4000,4003,4007,4010,4051,4057,4064,4068,4071,4077,4088,4092,4096,4102,4105,4111,4118,4127,4130,4136,4142,4146,4149,4155,4164,4167,4171,4174,4188,4191,4194,4198,4201,4205,4208,4211,4273,4276,4320,4334,4338,4341,4344,4347,4381,4391,4395,4398,4401,4405,4408,4430,4434,4449,4452,4489,4492,4520,4534,4538,4543,4551,4558,4565,4568,4573,4579,4583,4586,4589,4595,4601,4606,4610,4613,4724,4733,4735,4741,4747,4753,4759,4761,4764,4767,4777,4779,4783,4789,4793,4803,4807,4810,4814,4817,4821,4827,4829,4835,4838,4841,4843,4927],[11,3961,3963],{"id":3962},"cls-explained-cumulative-layout-shift","CLS Explained: Cumulative Layout Shift",[16,3965,3966,3967,3970],{},"A page can load quickly and still feel broken. You start reading, an image appears, the text suddenly moves downward, and the button you were about to click jumps somewhere else. That instability is what ",[28,3968,3969],{},"Cumulative Layout Shift (CLS)"," is designed to measure.",[16,3972,3973,3974,52],{},"CLS is one of Google's three Core Web Vitals, alongside Largest Contentful Paint (LCP) and Interaction to Next Paint (INP). Unlike those metrics, CLS is not measured in milliseconds. It produces a unitless score that represents how much visible content moved unexpectedly and how significant that movement was. (",[46,3975,423],{"href":3976,"rel":3977},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fcls?authuser=6",[50],[11,3979,3981],{"id":3980},"what-is-cls","What Is CLS?",[16,3983,3984],{},[28,3985,3986],{},"Cumulative Layout Shift measures the visual stability of a web page by quantifying unexpected movement of visible content.",[16,3988,3989,3990,3993,3994,52],{},"A layout shift occurs when a visible element changes its starting position between two rendered frames. CLS then groups unexpected shifts into short bursts called ",[28,3991,3992],{},"session windows"," and reports the session window with the largest combined shift score. (",[46,3995,423],{"href":3976,"rel":3996},[50],[16,3998,3999],{},"A practical example is an article where the browser initially renders the headline and text, then an image without reserved dimensions loads above them. The image takes up space, pushes the article downward, and forces the reader to find their place again.",[16,4001,4002],{},"That movement contributes to CLS.",[11,4004,4006],{"id":4005},"cls-score","CLS Score",[16,4008,4009],{},"Google's current thresholds are:",[65,4011,4012,4022],{},[68,4013,4014],{},[71,4015,4016,4019],{},[74,4017,4018],{},"CLS",[74,4020,4021],{},"Assessment",[84,4023,4024,4033,4042],{},[71,4025,4026,4031],{},[89,4027,4028],{},[28,4029,4030],{},"0.10 or lower",[89,4032,2547],{},[71,4034,4035,4040],{},[89,4036,4037],{},[28,4038,4039],{},"Above 0.10 to 0.25",[89,4041,2555],{},[71,4043,4044,4049],{},[89,4045,4046],{},[28,4047,4048],{},"Above 0.25",[89,4050,2563],{},[16,4052,4053,4054,4056],{},"For Core Web Vitals evaluation, Google recommends looking at the ",[28,4055,2569],{},", segmented between mobile and desktop. In practical terms, at least 75% of visits should experience a CLS of 0.10 or lower.",[16,4058,4059,4060,4063],{},"CLS is unitless. A score of ",[20,4061,4062],{},"0.1"," does not mean 0.1 seconds. It represents the combined severity of unexpected visual movement.",[11,4065,4067],{"id":4066},"why-cls-matters","Why CLS Matters",[16,4069,4070],{},"Layout instability directly affects usability.",[16,4072,4073,4074,52],{},"A shift can make someone lose their reading position, cause a form control to move while they are interacting with it, or make a user accidentally click a different button from the one they intended. The problem becomes especially noticeable on slower networks, where images, advertisements, fonts, API responses, and third-party content may arrive later than they do during local development. (",[46,4075,423],{"href":3976,"rel":4076},[50],[16,4078,4079,4080,4082,4083,52],{},"CLS also matters to search performance. Google documents Core Web Vitals as signals used by its ranking systems and recommends achieving good Core Web Vitals for Search and user experience. However, a good CLS score does ",[28,4081,3050],{}," guarantee higher rankings. Google evaluates many signals, and Core Web Vitals are only one part of page experience. (",[46,4084,4087],{"href":4085,"rel":4086},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fcore-web-vitals?authuser=1",[50],"developers.google.com",[16,4089,4090],{},[177,4091,552],{},[11,4093,4095],{"id":4094},"how-cls-works","How CLS Works",[16,4097,4098,4099,59],{},"CLS starts with individual ",[28,4100,4101],{},"layout shift scores",[16,4103,4104],{},"For every relevant shift, the browser evaluates two factors:",[168,4106,4109],{"className":4107,"code":4108,"language":787,"meta":173},[785],"layout shift score = impact fraction × distance fraction\n",[20,4110,4108],{"__ignoreMap":173},[16,4112,4113,4114,4117],{},"The ",[28,4115,4116],{},"impact fraction"," represents how much of the viewport is affected by unstable elements before and after the movement.",[16,4119,4113,4120,4123,4124,52],{},[28,4121,4122],{},"distance fraction"," measures how far the most displaced unstable element moved relative to the viewport's largest dimension. (",[46,4125,423],{"href":3976,"rel":4126},[50],[16,4128,4129],{},"Suppose a moving element affects 75% of the viewport and moves a distance equivalent to 25% of the viewport's largest dimension:",[168,4131,4134],{"className":4132,"code":4133,"language":787,"meta":173},[785],"0.75 × 0.25 = 0.1875\n",[20,4135,4133],{"__ignoreMap":173},[16,4137,4138,4139,59],{},"The layout shift score for that event is therefore ",[20,4140,4141],{},"0.1875",[1632,4143,4145],{"id":4144},"session-windows","Session Windows",[16,4147,4148],{},"Modern CLS does not simply add every layout shift that occurs throughout a page's lifetime.",[16,4150,4151,4152,4154],{},"Individual unexpected shifts are grouped into ",[28,4153,3992],{},". A session window contains shifts separated by less than one second and can last for a maximum of five seconds.",[16,4156,4157,4158,578,4161,52],{},"The page's CLS is the combined score of the ",[28,4159,4160],{},"largest session window",[46,4162,423],{"href":3976,"rel":4163},[50],[16,4165,4166],{},"This approach prevents long-lived pages such as single-page applications and infinite-scroll interfaces from being automatically penalized simply because users keep them open longer.",[11,4168,4170],{"id":4169},"expected-shifts","Expected Shifts",[16,4172,4173],{},"Not every movement contributes to CLS.",[16,4175,4176,4177,4180,4181,4184,4185,52],{},"A shift caused directly by a discrete user interaction—such as a click, tap, or keypress—can be excluded when it happens within ",[28,4178,4179],{},"500 milliseconds"," of that interaction. The Layout Instability API exposes this through the ",[20,4182,4183],{},"hadRecentInput"," property. (",[46,4186,423],{"href":3976,"rel":4187},[50],[16,4189,4190],{},"For example, expanding an accordion immediately after a user clicks it is generally expected.",[16,4192,4193],{},"However, scrolling is different. Continuous interactions such as scrolling are not treated in the same way. If lazy-loaded content suddenly pushes existing content downward while the user scrolls, that movement can still contribute to CLS.",[11,4195,4197],{"id":4196},"common-cls-causes","Common CLS Causes",[16,4199,4200],{},"The most frequent causes are surprisingly ordinary.",[1632,4202,4204],{"id":4203},"unsized-images","Unsized Images",[16,4206,4207],{},"An image without known dimensions can initially occupy little or no layout space. Once the image loads, the browser discovers its size and moves surrounding content.",[16,4209,4210],{},"Reserve the required space using HTML dimensions:",[168,4212,4216],{"className":4213,"code":4214,"language":4215,"meta":173,"style":173},"language-html shiki shiki-themes github-light github-dark","\u003Cimg\n  src=\"product.jpg\"\n  width=\"1200\"\n  height=\"800\"\n  alt=\"Product\"\n>\n","html",[20,4217,4218,4227,4238,4248,4258,4268],{"__ignoreMap":173},[177,4219,4220,4223],{"class":179,"line":180},[177,4221,4222],{"class":183},"\u003C",[177,4224,4226],{"class":4225},"s9eBZ","img\n",[177,4228,4229,4232,4235],{"class":179,"line":215},[177,4230,4231],{"class":187},"  src",[177,4233,4234],{"class":183},"=",[177,4236,4237],{"class":194},"\"product.jpg\"\n",[177,4239,4240,4243,4245],{"class":179,"line":224},[177,4241,4242],{"class":187},"  width",[177,4244,4234],{"class":183},[177,4246,4247],{"class":194},"\"1200\"\n",[177,4249,4250,4253,4255],{"class":179,"line":235},[177,4251,4252],{"class":187},"  height",[177,4254,4234],{"class":183},[177,4256,4257],{"class":194},"\"800\"\n",[177,4259,4260,4263,4265],{"class":179,"line":241},[177,4261,4262],{"class":187},"  alt",[177,4264,4234],{"class":183},[177,4266,4267],{"class":194},"\"Product\"\n",[177,4269,4270],{"class":179,"line":247},[177,4271,4272],{"class":183},">\n",[16,4274,4275],{},"Responsive CSS can still resize the image:",[168,4277,4281],{"className":4278,"code":4279,"language":4280,"meta":173,"style":173},"language-css shiki shiki-themes github-light github-dark","img {\n  width: 100%;\n  height: auto;\n}\n","css",[20,4282,4283,4290,4305,4316],{"__ignoreMap":173},[177,4284,4285,4288],{"class":179,"line":180},[177,4286,4287],{"class":4225},"img",[177,4289,212],{"class":183},[177,4291,4292,4294,4297,4300,4303],{"class":179,"line":215},[177,4293,4242],{"class":497},[177,4295,4296],{"class":183},": ",[177,4298,4299],{"class":497},"100",[177,4301,4302],{"class":208},"%",[177,4304,459],{"class":183},[177,4306,4307,4309,4311,4314],{"class":179,"line":224},[177,4308,4252],{"class":497},[177,4310,4296],{"class":183},[177,4312,4313],{"class":497},"auto",[177,4315,459],{"class":183},[177,4317,4318],{"class":179,"line":235},[177,4319,511],{"class":183},[16,4321,4322,4323,2165,4326,4329,4330,52],{},"Modern browsers can use the ",[20,4324,4325],{},"width",[20,4327,4328],{},"height"," attributes to determine the image's aspect ratio before the image finishes loading. (",[46,4331,423],{"href":4332,"rel":4333},"https:\u002F\u002Fweb.dev\u002Farticles\u002Foptimize-cls",[50],[1632,4335,4337],{"id":4336},"ads-and-embeds","Ads and Embeds",[16,4339,4340],{},"Advertisements, video embeds, maps, social widgets, and iframes often load after the surrounding page.",[16,4342,4343],{},"If their container initially has no height, everything below it may move when the content appears.",[16,4345,4346],{},"Reserve predictable space:",[168,4348,4350],{"className":4278,"code":4349,"language":4280,"meta":173,"style":173},".video-wrapper {\n  aspect-ratio: 16 \u002F 9;\n}\n",[20,4351,4352,4359,4377],{"__ignoreMap":173},[177,4353,4354,4357],{"class":179,"line":180},[177,4355,4356],{"class":187},".video-wrapper",[177,4358,212],{"class":183},[177,4360,4361,4364,4366,4369,4372,4375],{"class":179,"line":215},[177,4362,4363],{"class":497},"  aspect-ratio",[177,4365,4296],{"class":183},[177,4367,4368],{"class":497},"16",[177,4370,4371],{"class":183}," \u002F ",[177,4373,4374],{"class":497},"9",[177,4376,459],{"class":183},[177,4378,4379],{"class":179,"line":224},[177,4380,511],{"class":183},[16,4382,4383,4384,4387,4388,52],{},"For variable-height content, a suitable ",[20,4385,4386],{},"min-height"," or placeholder can reduce movement. Removing reserved space when no advertisement appears can itself create another layout shift, so placeholders need to be designed carefully. (",[46,4389,423],{"href":4332,"rel":4390},[50],[1632,4392,4394],{"id":4393},"dynamic-content","Dynamic Content",[16,4396,4397],{},"Cookie notices, promotional banners, alerts, recommendations, and asynchronously loaded components can cause large shifts when inserted above content the user is already viewing.",[16,4399,4400],{},"Prefer reserving space beforehand or, where appropriate, displaying the component as an overlay rather than inserting it into the document flow.",[1632,4402,4404],{"id":4403},"web-fonts","Web Fonts",[16,4406,4407],{},"A fallback font and the final web font can have different character widths, line heights, or metrics. When the real font arrives, text may wrap differently and move surrounding content.",[16,4409,4410,4411,4414,4415,406,4418,406,4421,410,4424,578,4427,52],{},"Possible improvements include selecting a closer fallback font, loading critical fonts earlier, using ",[20,4412,4413],{},"font-display"," appropriately, and adjusting fallback font metrics with properties such as ",[20,4416,4417],{},"size-adjust",[20,4419,4420],{},"ascent-override",[20,4422,4423],{},"descent-override",[20,4425,4426],{},"line-gap-override",[46,4428,423],{"href":4332,"rel":4429},[50],[1632,4431,4433],{"id":4432},"layout-based-animations","Layout-Based Animations",[16,4435,4436,4437,406,4440,406,4443,4445,4446,4448],{},"Animating properties such as ",[20,4438,4439],{},"top",[20,4441,4442],{},"left",[20,4444,4325],{},", or ",[20,4447,4328],{}," can change layout.",[16,4450,4451],{},"Where possible, use compositor-friendly transforms:",[168,4453,4455],{"className":4278,"code":4454,"language":4280,"meta":173,"style":173},".card {\n  transform: translateY(20px);\n}\n",[20,4456,4457,4464,4485],{"__ignoreMap":173},[177,4458,4459,4462],{"class":179,"line":180},[177,4460,4461],{"class":187},".card",[177,4463,212],{"class":183},[177,4465,4466,4469,4471,4474,4476,4479,4482],{"class":179,"line":215},[177,4467,4468],{"class":497},"  transform",[177,4470,4296],{"class":183},[177,4472,4473],{"class":497},"translateY",[177,4475,191],{"class":183},[177,4477,4478],{"class":497},"20",[177,4480,4481],{"class":208},"px",[177,4483,4484],{"class":183},");\n",[177,4486,4487],{"class":179,"line":224},[177,4488,511],{"class":183},[16,4490,4491],{},"instead of repeatedly changing:",[168,4493,4495],{"className":4278,"code":4494,"language":4280,"meta":173,"style":173},".card {\n  top: 20px;\n}\n",[20,4496,4497,4503,4516],{"__ignoreMap":173},[177,4498,4499,4501],{"class":179,"line":180},[177,4500,4461],{"class":187},[177,4502,212],{"class":183},[177,4504,4505,4508,4510,4512,4514],{"class":179,"line":215},[177,4506,4507],{"class":497},"  top",[177,4509,4296],{"class":183},[177,4511,4478],{"class":497},[177,4513,4481],{"class":208},[177,4515,459],{"class":183},[177,4517,4518],{"class":179,"line":224},[177,4519,511],{"class":183},[16,4521,4522,4523,4526,4527,4530,4531,52],{},"Using ",[20,4524,4525],{},"transform: translate()"," or ",[20,4528,4529],{},"transform: scale()"," can visually move elements without creating the same type of layout shift. (",[46,4532,423],{"href":3976,"rel":4533},[50],[11,4535,4537],{"id":4536},"how-to-measure-cls","How to Measure CLS",[16,4539,4540,4541,59],{},"Start with ",[28,4542,2761],{},[16,4544,4545,4546,52],{},"Chrome UX Report (CrUX) contains aggregated real-user Core Web Vitals data, including CLS. PageSpeed Insights can display CrUX field data where sufficient data is available, while Search Console groups pages through its Core Web Vitals report. CrUX reports CLS at the 75th percentile and treats CLS as a unitless metric. (",[46,4547,4550],{"href":4548,"rel":4549},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fcrux\u002Fapi?utm_source=chatgpt.com",[50],"developer.chrome.com",[16,4552,4553,4554,4557],{},"Then use ",[28,4555,4556],{},"lab tools"," to investigate the problem.",[16,4559,4560,4561,52],{},"Chrome DevTools' Performance panel exposes individual layout shifts and groups them into clusters. You can inspect shift scores, affected elements, timing, screenshots, and potential culprits. Chrome's Rendering tools can also highlight layout-shift regions visually. (",[46,4562,4550],{"href":4563,"rel":4564},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fdevtools\u002Fperformance\u002Freference?authuser=1&hl=en&utm_source=chatgpt.com",[50],[16,4566,4567],{},"A useful workflow is:",[16,4569,4570],{},[28,4571,4572],{},"Field CLS is poor → reproduce the page → identify the largest shift cluster → inspect the shifted elements → locate the element that caused the movement → fix it → measure again.",[16,4574,4575,4576,52],{},"Do not assume the element that moved is the root cause. A paragraph may move because an advertisement, image, banner, or another component above it changed size. (",[46,4577,423],{"href":4332,"rel":4578},[50],[11,4580,4582],{"id":4581},"lab-vs-field-cls","Lab vs Field CLS",[16,4584,4585],{},"One common debugging mistake is expecting Lighthouse and real-user CLS to match exactly.",[16,4587,4588],{},"They measure different situations.",[16,4590,4591,4592,52],{},"A normal Lighthouse test primarily observes the initial page load. Real users may continue scrolling, opening menus, loading more products, triggering route changes, or keeping a page open for several minutes. Unexpected shifts happening later can therefore appear in CrUX even when a simple Lighthouse load looks stable. (",[46,4593,423],{"href":4332,"rel":4594},[50],[16,4596,4597,4598,59],{},"When lab CLS is low but field CLS is high, investigate ",[28,4599,4600],{},"post-load interactions and scrolling behavior",[16,4602,4603],{},[177,4604,4605],{},"INTERNAL LINK: Lab Data vs Field Data",[11,4607,4609],{"id":4608},"cls-debugging","CLS Debugging",[16,4611,4612],{},"For difficult cases, Chromium exposes layout shifts through the Layout Instability API:",[168,4614,4616],{"className":170,"code":4615,"language":172,"meta":173,"style":173},"new PerformanceObserver((entryList) => {\n  for (const entry of entryList.getEntries()) {\n    if (!entry.hadRecentInput) {\n      console.log('Layout shift:', entry.value, entry.sources);\n    }\n  }\n}).observe({\n  type: 'layout-shift',\n  buffered: true\n});\n",[20,4617,4618,4636,4656,4669,4684,4688,4693,4702,4712,4720],{"__ignoreMap":173},[177,4619,4620,4623,4625,4627,4630,4632,4634],{"class":179,"line":180},[177,4621,4622],{"class":208},"new",[177,4624,604],{"class":187},[177,4626,607],{"class":183},[177,4628,4629],{"class":201},"entryList",[177,4631,205],{"class":183},[177,4633,209],{"class":208},[177,4635,212],{"class":183},[177,4637,4638,4641,4643,4645,4647,4649,4652,4654],{"class":179,"line":215},[177,4639,4640],{"class":208},"  for",[177,4642,624],{"class":183},[177,4644,592],{"class":208},[177,4646,629],{"class":497},[177,4648,632],{"class":208},[177,4650,4651],{"class":183}," entryList.",[177,4653,638],{"class":187},[177,4655,641],{"class":183},[177,4657,4658,4661,4663,4666],{"class":179,"line":224},[177,4659,4660],{"class":208},"    if",[177,4662,624],{"class":183},[177,4664,4665],{"class":208},"!",[177,4667,4668],{"class":183},"entry.hadRecentInput) {\n",[177,4670,4671,4674,4676,4678,4681],{"class":179,"line":235},[177,4672,4673],{"class":183},"      console.",[177,4675,2847],{"class":187},[177,4677,191],{"class":183},[177,4679,4680],{"class":194},"'Layout shift:'",[177,4682,4683],{"class":183},", entry.value, entry.sources);\n",[177,4685,4686],{"class":179,"line":241},[177,4687,693],{"class":183},[177,4689,4690],{"class":179,"line":247},[177,4691,4692],{"class":183},"  }\n",[177,4694,4695,4698,4700],{"class":179,"line":253},[177,4696,4697],{"class":183},"}).",[177,4699,709],{"class":187},[177,4701,221],{"class":183},[177,4703,4704,4707,4710],{"class":179,"line":259},[177,4705,4706],{"class":183},"  type: ",[177,4708,4709],{"class":194},"'layout-shift'",[177,4711,232],{"class":183},[177,4713,4714,4717],{"class":179,"line":265},[177,4715,4716],{"class":183},"  buffered: ",[177,4718,4719],{"class":497},"true\n",[177,4721,4722],{"class":179,"line":271},[177,4723,274],{"class":183},[16,4725,4726,4727,4729,4730,52],{},"This is useful for debugging individual shifts, but it is not a complete implementation of the CLS metric. Correct CLS calculation requires grouping shifts into session windows and handling additional lifecycle cases. For production Real User Monitoring, the ",[20,4728,432],{}," library is generally safer than reimplementing the complete metric yourself. (",[46,4731,423],{"href":3976,"rel":4732},[50],[11,4734,1630],{"id":1629},[16,4736,4737,4740],{},[28,4738,4739],{},"“CLS measures loading speed.”","\nNo. CLS measures visual stability. A page can load quickly and still have terrible CLS.",[16,4742,4743,4746],{},[28,4744,4745],{},"“Any movement increases CLS.”","\nNo. CLS focuses on unexpected layout shifts. Some shifts associated closely with discrete user input are excluded.",[16,4748,4749,4752],{},[28,4750,4751],{},"“A Lighthouse CLS of zero means users see zero CLS.”","\nNot necessarily. Post-load shifts may appear in field data but never occur during a simple synthetic page-load test.",[16,4754,4755,4758],{},[28,4756,4757],{},"“The shifted element caused the problem.”","\nNot always. It may simply have been pushed by another element.",[11,4760,899],{"id":898},[16,4762,4763],{},"Treat CLS as a layout architecture problem rather than a score to optimize after development.",[16,4765,4766],{},"Reserve space for media and third-party components before they load. Design asynchronous UI so loading does not unexpectedly displace existing content. Test pages under realistic network conditions and user flows, not only during initial load.",[16,4768,4769,4770,4773,4774,59],{},"For production sites, combine field monitoring with DevTools debugging. Field data tells you ",[28,4771,4772],{},"whether real users experience instability","; diagnostic tooling helps determine ",[28,4775,4776],{},"why",[11,4778,919],{"id":918},[921,4780,4782],{"id":4781},"is-cls-part-of-core-web-vitals","Is CLS part of Core Web Vitals?",[16,4784,4785,4786,52],{},"Yes. CLS is the Core Web Vital that measures visual stability. The other current Core Web Vitals are LCP for loading performance and INP for responsiveness. (",[46,4787,4087],{"href":4085,"rel":4788},[50],[921,4790,4792],{"id":4791},"what-is-a-good-cls","What is a good CLS?",[16,4794,4795,4796,4799,4800,52],{},"A CLS of ",[28,4797,4798],{},"0.10 or lower at the 75th percentile of page visits"," is considered good. (",[46,4801,423],{"href":3976,"rel":4802},[50],[921,4804,4806],{"id":4805},"is-cls-measured-in-seconds","Is CLS measured in seconds?",[16,4808,4809],{},"No. CLS is a unitless score.",[921,4811,4813],{"id":4812},"can-lazy-loading-increase-cls","Can lazy loading increase CLS?",[16,4815,4816],{},"Lazy loading itself is not necessarily the problem. CLS occurs when lazy-loaded content appears without sufficient space having already been reserved.",[921,4818,4820],{"id":4819},"can-cls-happen-after-page-load","Can CLS happen after page load?",[16,4822,4823,4824,52],{},"Yes. Unexpected shifts can occur during scrolling, dynamic content updates, SPA transitions, or other post-load behavior. This is one reason field CLS may be higher than Lighthouse CLS. (",[46,4825,423],{"href":4332,"rel":4826},[50],[11,4828,952],{"id":951},[16,4830,4831,4832],{},"CLS answers a simple question: ",[28,4833,4834],{},"does the page stay where the user expects it to stay?",[16,4836,4837],{},"A good CLS is not achieved by making every page static. Modern interfaces can still load content dynamically, animate elements, and react to user input. The important principle is predictability: reserve space before content arrives, avoid unexpectedly moving existing content, and validate the result using real-user data.",[16,4839,4840],{},"When a layout is stable by design, a good CLS score usually follows.",[11,4842,980],{"id":979},[1745,4844,4845,4858,4871,4885,4898,4914],{},[382,4846,4847,4848,4850,4851,624,4855,52],{},"web.dev — ",[28,4849,3969],{},". Last updated April 12, 2023. ",[46,4852,3969],{"href":4853,"rel":4854},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fcls?utm_source=chatgpt.com",[50],[46,4856,423],{"href":3976,"rel":4857},[50],[382,4859,4847,4860,4863,4864,624,4868,52],{},[28,4861,4862],{},"Optimize Cumulative Layout Shift",". Published May 5, 2020; updated February 7, 2025. ",[46,4865,4862],{"href":4866,"rel":4867},"https:\u002F\u002Fweb.dev\u002Farticles\u002Foptimize-cls?utm_source=chatgpt.com",[50],[46,4869,423],{"href":4332,"rel":4870},[50],[382,4872,4847,4873,4876,4877,624,4881,52],{},[28,4874,4875],{},"Debug layout shifts",". Published March 11, 2021; updated February 7, 2025. ",[46,4878,4875],{"href":4879,"rel":4880},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fdebug-layout-shifts?utm_source=chatgpt.com",[50],[46,4882,423],{"href":4883,"rel":4884},"https:\u002F\u002Fweb.dev\u002Farticles\u002Fdebug-layout-shifts",[50],[382,4886,2365,4887,4890,4891,624,4895,52],{},[28,4888,4889],{},"Understanding Core Web Vitals and Google search results",". Last updated December 10, 2025. ",[46,4892,4894],{"href":3193,"rel":4893},[50],"Google Search Central Core Web Vitals documentation",[46,4896,4087],{"href":4085,"rel":4897},[50],[382,4899,4900,4901,4904,4905,624,4910,52],{},"Chrome for Developers — ",[28,4902,4903],{},"Chrome UX Report: Metrics",". Published June 23, 2022; updated September 15, 2026. ",[46,4906,4909],{"href":4907,"rel":4908},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fcrux\u002Fmethodology\u002Fmetrics?utm_source=chatgpt.com",[50],"Chrome UX Report Metrics",[46,4911,4550],{"href":4912,"rel":4913},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fcrux\u002Fmethodology\u002Fmetrics?authuser=804924846",[50],[382,4915,4900,4916,1010,4919,624,4924,52],{},[28,4917,4918],{},"Performance features reference",[46,4920,4923],{"href":4921,"rel":4922},"https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fdevtools\u002Fperformance\u002Freference?utm_source=chatgpt.com",[50],"Chrome DevTools Performance reference",[46,4925,4550],{"href":4563,"rel":4926},[50],[1086,4928,4929],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":173,"searchDepth":215,"depth":215,"links":4931},[4932,4933,4934,4935,4936,4939,4940,4947,4948,4949,4950,4951,4952,4953,4954],{"id":3962,"depth":215,"text":3963},{"id":3980,"depth":215,"text":3981},{"id":4005,"depth":215,"text":4006},{"id":4066,"depth":215,"text":4067},{"id":4094,"depth":215,"text":4095,"children":4937},[4938],{"id":4144,"depth":224,"text":4145},{"id":4169,"depth":215,"text":4170},{"id":4196,"depth":215,"text":4197,"children":4941},[4942,4943,4944,4945,4946],{"id":4203,"depth":224,"text":4204},{"id":4336,"depth":224,"text":4337},{"id":4393,"depth":224,"text":4394},{"id":4403,"depth":224,"text":4404},{"id":4432,"depth":224,"text":4433},{"id":4536,"depth":215,"text":4537},{"id":4581,"depth":215,"text":4582},{"id":4608,"depth":215,"text":4609},{"id":1629,"depth":215,"text":1630},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Performance","Learn what Cumulative Layout Shift (CLS) measures, how the score works, what causes layout shifts, and how to diagnose and improve CLS.","\u002Fcls-defination.png","image of CLS",{},"\u002Fblog\u002Fen\u002Fcls-explained","2026-09-20",{"title":3957,"description":4956},"cls-explained","blog\u002Fen\u002Fcls-explained",1808,"EKUPABHygRE5uM4sr_MiJCbIlRz5VGJHqkLGGvDJgII",{"id":4968,"title":4969,"author":6,"body":4970,"category":1838,"description":5855,"draft":1106,"extension":1107,"featured":280,"image":5856,"imageAlt":5857,"locale":1110,"meta":5858,"navigation":280,"path":5859,"publishedAt":4961,"readingTime":265,"seo":5860,"slug":5861,"stem":5862,"translationKey":5861,"updatedAt":4961,"wordCount":5863,"__hash__":5864},"blog\u002Fblog\u002Fen\u002Fcrawling-in-seo.md","What Is Crawling in SEO? How Search Crawlers Work",{"type":8,"value":4971,"toc":5834},[4972,4976,4982,5002,5005,5007,5012,5015,5024,5028,5031,5095,5098,5103,5107,5110,5115,5118,5123,5126,5152,5167,5170,5175,5192,5210,5214,5217,5221,5228,5231,5237,5242,5246,5249,5251,5273,5291,5296,5300,5306,5308,5325,5337,5339,5342,5346,5349,5354,5357,5368,5374,5377,5386,5389,5419,5429,5434,5438,5441,5447,5453,5458,5461,5464,5478,5481,5484,5504,5510,5513,5518,5522,5525,5536,5539,5588,5591,5593,5602,5611,5620,5626,5628,5635,5638,5641,5644,5646,5650,5656,5660,5666,5670,5676,5680,5683,5687,5690,5692,5695,5701,5704,5706,5831],[11,4973,4975],{"id":4974},"what-is-crawling-in-seo","What Is Crawling in SEO?",[16,4977,4978,4979,59],{},"Before a search engine can understand or rank a web page, it usually has to find and retrieve it. That process is called ",[28,4980,4981],{},"crawling",[16,4983,4984,4985,406,4988,4445,4991,4994,4995,4998,4999,52],{},"Search engines use automated programs called ",[28,4986,4987],{},"crawlers",[28,4989,4990],{},"bots",[28,4992,4993],{},"spiders"," to discover URLs and request their content. Google’s primary search crawler is called ",[28,4996,4997],{},"Googlebot",". It can discover pages through links, sitemaps, previously known URLs, and other signals, then fetch those URLs so their content can move into later search-processing stages. (",[46,5000,4087],{"href":2372,"rel":5001},[50],[16,5003,5004],{},"Crawling sounds simple, but problems with links, robots.txt, servers, redirects, JavaScript, or URL architecture can stop important pages from being discovered efficiently.",[11,5006,41],{"id":40},[16,5008,5009],{},[28,5010,5011],{},"Crawling in SEO is the process search engine bots use to discover and retrieve URLs from the web.",[16,5013,5014],{},"A crawler finds a URL, checks whether it is allowed to access it, sends a request to the server, receives the response, and may extract additional URLs from the page.",[16,5016,5017,5018,5020,5021,52],{},"Crawling does ",[28,5019,3050],{}," mean a page is indexed or will rank. It only makes the page available for further processing. Google explicitly notes that not every crawled page is eventually indexed. (",[46,5022,4087],{"href":2372,"rel":5023},[50],[11,5025,5027],{"id":5026},"crawling-vs-indexing","Crawling vs Indexing",[16,5029,5030],{},"These concepts are closely related but are not interchangeable.",[65,5032,5033,5043],{},[68,5034,5035],{},[71,5036,5037,5040],{},[74,5038,5039],{},"Stage",[74,5041,5042],{},"What happens",[84,5044,5045,5055,5065,5075,5085],{},[71,5046,5047,5052],{},[89,5048,5049],{},[28,5050,5051],{},"Discovery",[89,5053,5054],{},"The search engine becomes aware that a URL exists.",[71,5056,5057,5062],{},[89,5058,5059],{},[28,5060,5061],{},"Crawling",[89,5063,5064],{},"A crawler requests and retrieves the URL.",[71,5066,5067,5072],{},[89,5068,5069],{},[28,5070,5071],{},"Rendering",[89,5073,5074],{},"When necessary, the crawler processes the page and its JavaScript-generated content.",[71,5076,5077,5082],{},[89,5078,5079],{},[28,5080,5081],{},"Indexing",[89,5083,5084],{},"Search systems analyze the content and decide whether and how it should enter the search index.",[71,5086,5087,5092],{},[89,5088,5089],{},[28,5090,5091],{},"Serving",[89,5093,5094],{},"Indexed information may be selected for relevant search results.",[16,5096,5097],{},"A page can therefore be discovered but not crawled, crawled but not indexed, or indexed without ranking prominently for a particular query.",[16,5099,5100],{},[177,5101,5102],{},"INTERNAL LINK: What Is Indexing in SEO?",[11,5104,5106],{"id":5105},"how-crawling-works","How Crawling Works",[16,5108,5109],{},"A simplified crawling sequence looks like this:",[16,5111,5112],{},[28,5113,5114],{},"URL discovered → crawling permissions checked → HTTP request → server response → content processed → links discovered → indexing systems",[16,5116,5117],{},"Suppose Googlebot already knows this page:",[16,5119,5120],{},[20,5121,5122],{},"https:\u002F\u002Fexample.com\u002Fblog\u002F",[16,5124,5125],{},"The page contains a standard HTML link:",[168,5127,5129],{"className":4213,"code":5128,"language":4215,"meta":173,"style":173},"\u003Ca href=\"\u002Fblog\u002Ftechnical-seo\u002F\">Technical SEO\u003C\u002Fa>\n",[20,5130,5131],{"__ignoreMap":173},[177,5132,5133,5135,5137,5140,5142,5145,5148,5150],{"class":179,"line":180},[177,5134,4222],{"class":183},[177,5136,46],{"class":4225},[177,5138,5139],{"class":187}," href",[177,5141,4234],{"class":183},[177,5143,5144],{"class":194},"\"\u002Fblog\u002Ftechnical-seo\u002F\"",[177,5146,5147],{"class":183},">Technical SEO\u003C\u002F",[177,5149,46],{"class":4225},[177,5151,4272],{"class":183},[16,5153,5154,5155,5158,5159,5162,5163,52],{},"Google can extract that URL and add it to the URLs it may crawl. Google specifically recommends using crawlable ",[20,5156,5157],{},"\u003Ca>"," elements with an ",[20,5160,5161],{},"href"," attribute for links you want its crawlers to follow reliably. (",[46,5164,4087],{"href":5165,"rel":5166},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Flinks-crawlable?utm_source=chatgpt.com",[50],[16,5168,5169],{},"The crawler may then request:",[16,5171,5172],{},[20,5173,5174],{},"https:\u002F\u002Fexample.com\u002Fblog\u002Ftechnical-seo\u002F",[16,5176,5177,5178,5180,5181,5184,5185,5188,5189,59],{},"Your server might respond with ",[20,5179,22],{},", a redirect such as ",[20,5182,5183],{},"301",", an error such as ",[20,5186,5187],{},"404",", or a server failure such as ",[20,5190,5191],{},"503",[16,5193,5194,5195,5198,5199,5201,5202,5205,5206,52],{},"A successful ",[20,5196,5197],{},"2xx"," response allows Google to pass the retrieved content into further processing, but even a successful response does not guarantee indexing. Persistent ",[20,5200,2190],{}," errors and ",[20,5203,5204],{},"429 Too Many Requests"," responses can cause Google to reduce its crawling rate. (",[46,5207,4087],{"href":5208,"rel":5209},"https:\u002F\u002Fdevelopers.google.com\u002Fcrawling\u002Fdocs\u002Ftroubleshooting\u002Fhttp-status-codes?authuser=19&utm_source=chatgpt.com",[50],[11,5211,5213],{"id":5212},"how-crawlers-find-urls","How Crawlers Find URLs",[16,5215,5216],{},"Search engines do not need you to submit every page manually.",[1632,5218,5220],{"id":5219},"internal-and-external-links","Internal and External Links",[16,5222,5223,5224,52],{},"Links are one of the primary discovery mechanisms. Google documents that Googlebot discovers new URLs mainly through links found on pages it already knows. (",[46,5225,4087],{"href":5226,"rel":5227},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fgooglebot?utm_source=chatgpt.com",[50],[16,5229,5230],{},"This makes internal linking part of technical SEO, not just navigation.",[16,5232,5233,5234,59],{},"An important page that has no crawlable links pointing to it may be harder for crawlers to discover. Such pages are commonly described as ",[28,5235,5236],{},"orphan pages",[16,5238,5239],{},[177,5240,5241],{},"INTERNAL LINK: Internal Linking for SEO",[1632,5243,5245],{"id":5244},"xml-sitemaps","XML Sitemaps",[16,5247,5248],{},"An XML sitemap provides search engines with a structured list of URLs you consider relevant.",[16,5250,2065],{},[168,5252,5256],{"className":5253,"code":5254,"language":5255,"meta":173,"style":173},"language-xml shiki shiki-themes github-light github-dark","\u003Curl>\n  \u003Cloc>https:\u002F\u002Fexample.com\u002Fblog\u002Ftechnical-seo\u002F\u003C\u002Floc>\n\u003C\u002Furl>\n","xml",[20,5257,5258,5263,5268],{"__ignoreMap":173},[177,5259,5260],{"class":179,"line":180},[177,5261,5262],{},"\u003Curl>\n",[177,5264,5265],{"class":179,"line":215},[177,5266,5267],{},"  \u003Cloc>https:\u002F\u002Fexample.com\u002Fblog\u002Ftechnical-seo\u002F\u003C\u002Floc>\n",[177,5269,5270],{"class":179,"line":224},[177,5271,5272],{},"\u003C\u002Furl>\n",[16,5274,5275,5276,5279,5280,4526,5283,5286,5287,52],{},"Google describes sitemap submission as a ",[28,5277,5278],{},"hint",", not a command or guarantee that every listed URL will be crawled or indexed. A single sitemap is limited to ",[28,5281,5282],{},"50,000 URLs",[28,5284,5285],{},"50 MB uncompressed","; larger sites can use multiple sitemaps and a sitemap index. (",[46,5288,4087],{"href":5289,"rel":5290},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fsitemaps\u002Fbuild-sitemap?authuser=77&utm_source=chatgpt.com",[50],[16,5292,5293],{},[177,5294,5295],{},"INTERNAL LINK: XML Sitemaps Explained",[11,5297,5299],{"id":5298},"robotstxt-and-crawling","robots.txt and Crawling",[16,5301,5302,5303,5305],{},"A ",[20,5304,2010],{}," file can tell compliant crawlers which URL paths they are allowed or disallowed to request.",[16,5307,2065],{},[168,5309,5313],{"className":5310,"code":5311,"language":5312,"meta":173,"style":173},"language-txt shiki shiki-themes github-light github-dark","User-agent: *\nDisallow: \u002Fadmin\u002F\n","txt",[20,5314,5315,5320],{"__ignoreMap":173},[177,5316,5317],{"class":179,"line":180},[177,5318,5319],{},"User-agent: *\n",[177,5321,5322],{"class":179,"line":215},[177,5323,5324],{},"Disallow: \u002Fadmin\u002F\n",[16,5326,5327,5328,5331,5332,52],{},"The Robots Exclusion Protocol was standardized as ",[28,5329,5330],{},"RFC 9309"," in September 2022. The specification describes crawlers as automated clients and makes clear that robots.txt rules are not an access-control or authorization system. (",[46,5333,5336],{"href":5334,"rel":5335},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc9309.html?utm_source=chatgpt.com",[50],"rfc-editor.org",[16,5338,3547],{},[16,5340,5341],{},"If sensitive information must remain private, use authentication or another real access-control mechanism. Do not depend on robots.txt.",[1632,5343,5345],{"id":5344},"robotstxt-is-not-noindex","robots.txt Is Not noindex",[16,5347,5348],{},"A common SEO mistake is assuming:",[1573,5350,5351],{},[16,5352,5353],{},"“If I block a URL in robots.txt, Google cannot index it.”",[16,5355,5356],{},"That is not reliably true.",[16,5358,5359,5360,5363,5364,52],{},"Google may discover a blocked URL through links and potentially show the URL in search results without crawling its content. Google therefore recommends ",[20,5361,5362],{},"noindex"," when the objective is to prevent an accessible page from appearing in Google Search. (",[46,5365,4087],{"href":5366,"rel":5367},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Frobots\u002Fintro?authuser=1&utm_source=chatgpt.com",[50],[16,5369,5370,5371,5373],{},"There is an important catch: Google must be able to crawl the page to see its ",[20,5372,5362],{}," directive.",[16,5375,5376],{},"So this combination can be counterproductive:",[168,5378,5380],{"className":5310,"code":5379,"language":5312,"meta":173,"style":173},"Disallow: \u002Fprivate-page\u002F\n",[20,5381,5382],{"__ignoreMap":173},[177,5383,5384],{"class":179,"line":180},[177,5385,5379],{},[16,5387,5388],{},"combined with:",[168,5390,5392],{"className":4213,"code":5391,"language":4215,"meta":173,"style":173},"\u003Cmeta name=\"robots\" content=\"noindex\">\n",[20,5393,5394],{"__ignoreMap":173},[177,5395,5396,5398,5401,5404,5406,5409,5412,5414,5417],{"class":179,"line":180},[177,5397,4222],{"class":183},[177,5399,5400],{"class":4225},"meta",[177,5402,5403],{"class":187}," name",[177,5405,4234],{"class":183},[177,5407,5408],{"class":194},"\"robots\"",[177,5410,5411],{"class":187}," content",[177,5413,4234],{"class":183},[177,5415,5416],{"class":194},"\"noindex\"",[177,5418,4272],{"class":183},[16,5420,5421,5422,5424,5425,52],{},"If crawling is blocked, Googlebot may never retrieve the HTML containing the ",[20,5423,5362],{}," instruction. (",[46,5426,4087],{"href":5427,"rel":5428},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fblock-indexing?utm_source=chatgpt.com",[50],[16,5430,5431],{},[177,5432,5433],{},"INTERNAL LINK: robots.txt Explained",[11,5435,5437],{"id":5436},"javascript-and-rendering","JavaScript and Rendering",[16,5439,5440],{},"Modern websites may deliver only part of their meaningful content in the original HTML and generate the rest through JavaScript.",[16,5442,5443,5444,52],{},"Google documents that during its processing it can render pages and execute JavaScript using a recent version of Chrome. Rendering matters because content or links introduced by JavaScript may not exist in the initial HTML response. (",[46,5445,4087],{"href":2372,"rel":5446},[50],[16,5448,5449,5450,52],{},"However, JavaScript rendering does not remove the need for a technically crawlable website. Important links should still use standard link markup, essential resources should remain accessible, and developers should verify what Google actually receives and renders. (",[46,5451,4087],{"href":5165,"rel":5452},[50],[16,5454,5455],{},[177,5456,5457],{},"INTERNAL LINK: JavaScript SEO Basics",[11,5459,5460],{"id":2465},"Crawl Budget",[16,5462,5463],{},"Search engines cannot continuously crawl every URL on the web.",[16,5465,5466,5467,5470,5471,5474,5475,52],{},"Google describes ",[28,5468,5469],{},"crawl budget"," as the URLs its crawling systems ",[987,5472,5473],{},"can and want to crawl",", based mainly on crawl capacity and crawl demand. (",[46,5476,4087],{"href":2360,"rel":5477},[50],[16,5479,5480],{},"For most ordinary websites, crawl budget is not something that requires aggressive optimization.",[16,5482,5483],{},"Google’s current guidance is primarily aimed at very large or rapidly changing sites, including roughly:",[379,5485,5486,5493,5499],{},[382,5487,5488,5489,5492],{},"sites with ",[28,5490,5491],{},"1 million or more unique pages"," that change moderately often;",[382,5494,5488,5495,5498],{},[28,5496,5497],{},"10,000 or more unique pages"," that change very rapidly;",[382,5500,5501,5502,59],{},"sites with many URLs reported as ",[28,5503,1950],{},[16,5505,5506,5507,52],{},"Google explicitly says these numbers are rough classifications rather than exact thresholds. (",[46,5508,4087],{"href":2360,"rel":5509},[50],[16,5511,5512],{},"Large ecommerce sites, marketplaces, publishers, and sites with faceted navigation can create huge URL spaces through filters, sorting parameters, calendars, session IDs, or duplicates. In those situations, crawl efficiency becomes substantially more important.",[16,5514,5515],{},[177,5516,5517],{},"INTERNAL LINK: Crawl Budget Explained",[11,5519,5521],{"id":5520},"diagnosing-crawling-problems","Diagnosing Crawling Problems",[16,5523,5524],{},"If an important page is not appearing in search, first determine whether the problem is actually crawling.",[16,5526,5527,5528,5531,5532,52],{},"Check the URL with ",[28,5529,5530],{},"Google Search Console’s URL Inspection tool",". Google documents that it can show the current indexing status, test a live URL, request crawling, and provide information about loaded resources. (",[46,5533,4087],{"href":5534,"rel":5535},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fmonitor-debug\u002Fsearch-console-start?utm_source=chatgpt.com",[50],[16,5537,5538],{},"Then investigate:",[1745,5540,5541,5546,5551,5560,5571,5576,5582],{},[382,5542,5543,5545],{},[28,5544,5051],{}," — Is the page internally linked or included in the sitemap?",[382,5547,5548,5550],{},[28,5549,2010],{}," — Is Googlebot accidentally blocked?",[382,5552,5553,5556,5557,5559],{},[28,5554,5555],{},"HTTP response"," — Does the URL return the expected ",[20,5558,1904],{},", redirect, or error?",[382,5561,5562,5565,5566,4445,5568,5570],{},[28,5563,5564],{},"Server availability"," — Are DNS, network, timeout, ",[20,5567,2187],{},[20,5569,2190],{}," errors occurring?",[382,5572,5573,5575],{},[28,5574,5071],{}," — Is important content available after JavaScript processing?",[382,5577,5578,5581],{},[28,5579,5580],{},"URL duplication"," — Are filters or parameters producing unnecessary URL variations?",[382,5583,5584,5587],{},[28,5585,5586],{},"Server logs"," — Has Googlebot actually requested the URL?",[16,5589,5590],{},"For crawler-level debugging, server access logs are especially valuable because they show what was actually requested rather than what you assume a crawler did.",[11,5592,1630],{"id":1629},[16,5594,5595,5598,5599,52],{},[28,5596,5597],{},"“A sitemap guarantees crawling.”","\nNo. Google calls sitemaps a hint. (",[46,5600,4087],{"href":5289,"rel":5601},[50],[16,5603,5604,5607,5608,52],{},[28,5605,5606],{},"“Crawled means indexed.”","\nNo. Crawled content still has to pass later processing and indexing decisions. (",[46,5609,4087],{"href":2360,"rel":5610},[50],[16,5612,5613,5616,5617,52],{},[28,5614,5615],{},"“robots.txt removes pages from Google.”","\nNot necessarily. It primarily controls crawling. (",[46,5618,4087],{"href":5366,"rel":5619},[50],[16,5621,5622,5625],{},[28,5623,5624],{},"“More crawling always means better SEO.”","\nNot necessarily. The objective is efficient access to useful, important URLs—not maximizing crawler requests.",[11,5627,899],{"id":898},[16,5629,5630,5631,5634],{},"For most websites, crawling should be treated as an ",[28,5632,5633],{},"access and architecture problem",", not something to manipulate.",[16,5636,5637],{},"Make important pages discoverable through standard internal links, maintain an accurate sitemap, return correct HTTP responses, avoid accidentally blocking required pages or resources, and keep unnecessary URL variations under control.",[16,5639,5640],{},"Then verify the result with Search Console and server logs.",[16,5642,5643],{},"Only invest heavily in crawl-budget optimization when the site's scale or URL-generation behavior provides a real reason to do so.",[11,5645,919],{"id":918},[921,5647,5649],{"id":5648},"can-a-page-rank-without-being-crawled","Can a Page Rank Without Being Crawled?",[16,5651,5652,5653,52],{},"Search engines generally need to retrieve content before they can fully process and index it. A blocked URL may sometimes appear as a URL-only result based on external information, but its content cannot be processed normally if the crawler cannot retrieve it. (",[46,5654,4087],{"href":5366,"rel":5655},[50],[921,5657,5659],{"id":5658},"how-often-does-google-crawl-a-website","How Often Does Google Crawl a Website?",[16,5661,5662,5663,52],{},"There is no universal schedule. Googlebot algorithmically determines what to crawl, how frequently, and how many URLs to request while also trying to avoid overloading servers. (",[46,5664,4087],{"href":2372,"rel":5665},[50],[921,5667,5669],{"id":5668},"does-submitting-a-sitemap-make-google-crawl-faster","Does Submitting a Sitemap Make Google Crawl Faster?",[16,5671,5672,5673,52],{},"A sitemap can improve discovery, especially for new, updated, large, or difficult-to-discover URL sets, but submitting one does not guarantee immediate crawling. (",[46,5674,4087],{"href":5289,"rel":5675},[50],[921,5677,5679],{"id":5678},"should-every-page-be-crawlable","Should Every Page Be Crawlable?",[16,5681,5682],{},"No. Administrative URLs, duplicate URL combinations, internal search results, and other low-value URL spaces may reasonably be restricted depending on the site's architecture. Pages intended to appear in organic search, however, generally need to remain accessible to search crawlers.",[921,5684,5686],{"id":5685},"is-crawling-a-ranking-factor","Is Crawling a Ranking Factor?",[16,5688,5689],{},"Crawling is primarily a prerequisite for search systems to retrieve and process content. It should not be confused with a documented ranking signal. A page being crawled frequently does not by itself demonstrate that it will rank higher.",[11,5691,952],{"id":951},[16,5693,5694],{},"Crawling is the retrieval layer of search.",[16,5696,5697,5698,5700],{},"Search engine crawlers discover URLs, request them from servers, process the responses, and find additional URLs to explore. Good technical SEO makes that process predictable: important content is easy to discover and fetch, irrelevant URL spaces do not consume unnecessary resources, and directives such as robots.txt and ",[20,5699,5362],{}," are used for their correct purposes.",[16,5702,5703],{},"If crawling fails, the rest of the search pipeline may never get the content it needs.",[11,5705,980],{"id":979},[1745,5707,5708,5721,5733,5745,5758,5770,5781,5793,5805,5817],{},[382,5709,5710,5713,5714,624,5718,52],{},[28,5711,5712],{},"Google Search Central — In-Depth Guide to How Google Search Works."," Google for Developers. ",[46,5715,5717],{"href":2372,"rel":5716},[50],"How Google Search Works",[46,5719,4087],{"href":2372,"rel":5720},[50],[382,5722,5723,5713,5726,624,5730,52],{},[28,5724,5725],{},"Google Search Central — Googlebot.",[46,5727,5729],{"href":5226,"rel":5728},[50],"Googlebot documentation",[46,5731,4087],{"href":5226,"rel":5732},[50],[382,5734,5735,5713,5738,624,5742,52],{},[28,5736,5737],{},"Google Crawling Infrastructure — Optimize Your Crawl Budget.",[46,5739,5741],{"href":2360,"rel":5740},[50],"Crawl budget documentation",[46,5743,4087],{"href":2360,"rel":5744},[50],[382,5746,5747,5713,5750,624,5755,52],{},[28,5748,5749],{},"Google Search Central — Introduction to robots.txt.",[46,5751,5754],{"href":5752,"rel":5753},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Frobots\u002Fintro?utm_source=chatgpt.com",[50],"robots.txt introduction",[46,5756,4087],{"href":5366,"rel":5757},[50],[382,5759,5760,5763,5764,624,5767,52],{},[28,5761,5762],{},"Koster, M.; Illyes, G.; Zeller, H.; Sassman, L. — RFC 9309: Robots Exclusion Protocol."," IETF, September 2022. ",[46,5765,5330],{"href":5334,"rel":5766},[50],[46,5768,5336],{"href":5334,"rel":5769},[50],[382,5771,5772,5713,5775,624,5778,52],{},[28,5773,5774],{},"Google Search Central — Build and Submit a Sitemap.",[46,5776,2424],{"href":2422,"rel":5777},[50],[46,5779,4087],{"href":5289,"rel":5780},[50],[382,5782,5783,5713,5786,624,5790,52],{},[28,5784,5785],{},"Google Search Central — Link Best Practices for Google.",[46,5787,5789],{"href":5165,"rel":5788},[50],"Crawlable links documentation",[46,5791,4087],{"href":5165,"rel":5792},[50],[382,5794,5795,5713,5798,624,5802,52],{},[28,5796,5797],{},"Google Crawling Infrastructure — How HTTP Status Codes Affect Google's Crawlers.",[46,5799,5801],{"href":2412,"rel":5800},[50],"HTTP status code documentation",[46,5803,4087],{"href":5208,"rel":5804},[50],[382,5806,5807,5713,5810,624,5814,52],{},[28,5808,5809],{},"Google Search Central — Block Search Indexing with noindex.",[46,5811,5813],{"href":5427,"rel":5812},[50],"noindex documentation",[46,5815,4087],{"href":5427,"rel":5816},[50],[382,5818,5819,3873,5822,624,5827,52],{},[28,5820,5821],{},"Sitemaps.org — Sitemaps XML Format.",[46,5823,5826],{"href":5824,"rel":5825},"https:\u002F\u002Fwww.sitemaps.org\u002Fprotocol.html?utm_source=chatgpt.com",[50],"Sitemaps protocol",[46,5828,5830],{"href":5824,"rel":5829},[50],"sitemaps.org",[1086,5832,5833],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":173,"searchDepth":215,"depth":215,"links":5835},[5836,5837,5838,5839,5840,5844,5847,5848,5849,5850,5851,5852,5853,5854],{"id":4974,"depth":215,"text":4975},{"id":40,"depth":215,"text":41},{"id":5026,"depth":215,"text":5027},{"id":5105,"depth":215,"text":5106},{"id":5212,"depth":215,"text":5213,"children":5841},[5842,5843],{"id":5219,"depth":224,"text":5220},{"id":5244,"depth":224,"text":5245},{"id":5298,"depth":215,"text":5299,"children":5845},[5846],{"id":5344,"depth":224,"text":5345},{"id":5436,"depth":215,"text":5437},{"id":2465,"depth":215,"text":5460},{"id":5520,"depth":215,"text":5521},{"id":1629,"depth":215,"text":1630},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Learn what crawling means in SEO, how search engine bots discover and fetch URLs, how robots.txt, sitemaps and JavaScript affect crawling, and how to diagnose crawl problems.","\u002Fcrawling-in-seo.png","Explanation the Crawling in SEO",{},"\u002Fblog\u002Fen\u002Fcrawling-in-seo",{"title":4969,"description":5855},"crawling-in-seo","blog\u002Fen\u002Fcrawling-in-seo",1744,"znwR2lFSILsNULued9XebP8ytDMLr4YDbk3U1N2GTuY",{"id":5866,"title":5867,"author":6,"body":5868,"category":1838,"description":6688,"draft":1106,"extension":1107,"featured":280,"image":6689,"imageAlt":6690,"locale":1110,"meta":6691,"navigation":280,"path":6692,"publishedAt":4961,"readingTime":259,"seo":6693,"slug":6694,"stem":6695,"translationKey":6696,"updatedAt":4961,"wordCount":6697,"__hash__":6698},"blog\u002Fblog\u002Fen\u002Fdiscovers-urls.md","How Google Discovers New URLs: Links, Sitemaps and Crawling",{"type":8,"value":5869,"toc":6671},[5870,5874,5877,5887,5889,5904,5907,5912,5915,5919,6012,6018,6022,6028,6031,6038,6063,6069,6076,6079,6084,6088,6092,6095,6104,6129,6132,6163,6169,6175,6180,6184,6187,6189,6212,6219,6222,6228,6233,6242,6245,6249,6253,6256,6259,6265,6268,6274,6279,6288,6291,6297,6300,6306,6310,6316,6319,6325,6332,6341,6345,6349,6352,6385,6388,6395,6398,6402,6405,6412,6418,6440,6444,6447,6479,6486,6488,6497,6500,6503,6509,6512,6514,6518,6524,6528,6534,6538,6541,6545,6551,6555,6561,6563,6566,6569,6575,6577,6669],[11,5871,5873],{"id":5872},"how-google-discovers-new-urls","How Google Discovers New URLs",[16,5875,5876],{},"Publishing a page does not automatically mean Google knows that it exists. Before Google can crawl, understand, or index a page, its systems normally need to discover the page’s URL.",[16,5878,5879,5880,5883,5884,52],{},"Google calls this ",[28,5881,5882],{},"URL discovery",". According to Google’s documentation, new URLs are commonly found through links on pages Google already knows and through submitted sitemaps. Googlebot can then place discovered URLs into its crawling process, but discovery alone does not guarantee that a URL will be crawled, indexed, or shown in search results. (",[46,5885,4087],{"href":2372,"rel":5886},[50],[11,5888,41],{"id":40},[16,5890,5891,5892,5895,5896,5899,5900,52],{},"Google primarily discovers new URLs by ",[28,5893,5894],{},"following links from previously discovered pages"," and by ",[28,5897,5898],{},"reading sitemaps"," provided by website owners. Googlebot can also encounter URLs while processing redirects and links generated by JavaScript when those links are implemented in a crawlable way. (",[46,5901,4087],{"href":5902,"rel":5903},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Ffundamentals\u002Fget-started-developers?utm_source=chatgpt.com",[50],[16,5905,5906],{},"The important distinction is:",[16,5908,5909],{},[28,5910,5911],{},"Discovery → Crawling → Indexing → Serving",[16,5913,5914],{},"These are separate stages. A discovered URL is only a URL Google knows about. It is not automatically an indexed page.",[11,5916,5918],{"id":5917},"key-facts","Key Facts",[65,5920,5921,5934],{},[68,5922,5923],{},[71,5924,5925,5928,5931],{},[74,5926,5927],{},"Mechanism",[74,5929,5930],{},"Can help Google discover a URL?",[74,5932,5933],{},"Important limitation",[84,5935,5936,5947,5957,5967,5977,5987,6001],{},[71,5937,5938,5941,5944],{},[89,5939,5940],{},"Internal links",[89,5942,5943],{},"Yes",[89,5945,5946],{},"The link should be crawlable",[71,5948,5949,5952,5954],{},[89,5950,5951],{},"External links",[89,5953,5943],{},[89,5955,5956],{},"Google must encounter the linking page",[71,5958,5959,5962,5964],{},[89,5960,5961],{},"XML sitemap",[89,5963,5943],{},[89,5965,5966],{},"A sitemap is a hint, not a guarantee",[71,5968,5969,5972,5974],{},[89,5970,5971],{},"RSS\u002FAtom feed",[89,5973,5943],{},[89,5975,5976],{},"Usually covers recent content",[71,5978,5979,5982,5984],{},[89,5980,5981],{},"Redirect",[89,5983,5943],{},[89,5985,5986],{},"Googlebot may encounter the destination while navigating URLs",[71,5988,5989,5992,5994],{},[89,5990,5991],{},"JavaScript-generated link",[89,5993,5943],{},[89,5995,5996,5997,6000],{},"It should ultimately produce a crawlable ",[20,5998,5999],{},"\u003Ca href>"," link",[71,6002,6003,6006,6009],{},[89,6004,6005],{},"Search Console request",[89,6007,6008],{},"Yes, for URLs you manage",[89,6010,6011],{},"Requesting crawling does not guarantee indexing",[16,6013,6014,6015,52],{},"Google explicitly says that it does not maintain a central registry containing every web page. Its crawlers continuously discover new and updated URLs across the web instead. (",[46,6016,4087],{"href":2372,"rel":6017},[50],[11,6019,6021],{"id":6020},"links-are-the-main-discovery-path","Links Are the Main Discovery Path",[16,6023,6024,6025,52],{},"Googlebot discovers new URLs primarily from links embedded in pages that Google already knows about. Google’s documentation describes a simple example: a category or hub page links to a newly published blog post, allowing Google to discover that new URL. (",[46,6026,4087],{"href":2372,"rel":6027},[50],[16,6029,6030],{},"The same principle applies both internally and externally.",[16,6032,6033,6034,6037],{},"An ",[28,6035,6036],{},"internal link"," points from one page on your site to another:",[168,6039,6041],{"className":4213,"code":6040,"language":4215,"meta":173,"style":173},"\u003Ca href=\"\u002Fguides\u002Ftechnical-seo\">Technical SEO Guide\u003C\u002Fa>\n",[20,6042,6043],{"__ignoreMap":173},[177,6044,6045,6047,6049,6051,6053,6056,6059,6061],{"class":179,"line":180},[177,6046,4222],{"class":183},[177,6048,46],{"class":4225},[177,6050,5139],{"class":187},[177,6052,4234],{"class":183},[177,6054,6055],{"class":194},"\"\u002Fguides\u002Ftechnical-seo\"",[177,6057,6058],{"class":183},">Technical SEO Guide\u003C\u002F",[177,6060,46],{"class":4225},[177,6062,4272],{"class":183},[16,6064,6033,6065,6068],{},[28,6066,6067],{},"external link"," from another website can expose your URL through the same general crawling process.",[16,6070,6071,6072,52],{},"For important pages, Google recommends making sure each page has a link from at least one other page on your site. (",[46,6073,4087],{"href":6074,"rel":6075},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Flinks-crawlable?authuser=2&utm_source=chatgpt.com",[50],[16,6077,6078],{},"This is why site architecture matters for discovery. A page may exist perfectly well on your server but remain difficult for Google to find if nothing Google can crawl points to it.",[16,6080,6081,6082,59],{},"Pages with no meaningful internal links are commonly called ",[28,6083,5236],{},[16,6085,6086],{},[177,6087,5241],{},[11,6089,6091],{"id":6090},"links-must-be-crawlable","Links Must Be Crawlable",[16,6093,6094],{},"Not every clickable interface element is necessarily a link Google can reliably extract.",[16,6096,6097,6098,6100,6101,6103],{},"Google says the safest structure is an HTML ",[20,6099,5157],{}," element with an ",[20,6102,5161],{}," attribute:",[168,6105,6107],{"className":4213,"code":6106,"language":4215,"meta":173,"style":173},"\u003Ca href=\"\u002Fservices\u002Fseo\">SEO Services\u003C\u002Fa>\n",[20,6108,6109],{"__ignoreMap":173},[177,6110,6111,6113,6115,6117,6119,6122,6125,6127],{"class":179,"line":180},[177,6112,4222],{"class":183},[177,6114,46],{"class":4225},[177,6116,5139],{"class":187},[177,6118,4234],{"class":183},[177,6120,6121],{"class":194},"\"\u002Fservices\u002Fseo\"",[177,6123,6124],{"class":183},">SEO Services\u003C\u002F",[177,6126,46],{"class":4225},[177,6128,4272],{"class":183},[16,6130,6131],{},"Patterns based only on JavaScript event handlers are less reliable:",[168,6133,6135],{"className":4213,"code":6134,"language":4215,"meta":173,"style":173},"\u003Cspan onclick=\"openPage('\u002Fservices\u002Fseo')\">SEO Services\u003C\u002Fspan>\n",[20,6136,6137],{"__ignoreMap":173},[177,6138,6139,6141,6143,6146,6148,6151,6154,6157,6159,6161],{"class":179,"line":180},[177,6140,4222],{"class":183},[177,6142,177],{"class":4225},[177,6144,6145],{"class":187}," onclick",[177,6147,4234],{"class":183},[177,6149,6150],{"class":194},"\"",[177,6152,6153],{"class":187},"openPage",[177,6155,6156],{"class":194},"('\u002Fservices\u002Fseo')\"",[177,6158,6124],{"class":183},[177,6160,177],{"class":4225},[177,6162,4272],{"class":183},[16,6164,6165,6166,52],{},"Google can execute JavaScript, and JavaScript can insert links into the rendered DOM. However, Google still recommends implementing those links according to its crawlable-link guidance. (",[46,6167,4087],{"href":6074,"rel":6168},[50],[16,6170,6171,6172,52],{},"For JavaScript-heavy applications, every piece of content intended to appear as a separate search result should also have its own URL. (",[46,6173,4087],{"href":5902,"rel":6174},[50],[16,6176,6177],{},[177,6178,6179],{},"INTERNAL LINK: JavaScript SEO Explained",[11,6181,6183],{"id":6182},"sitemaps-help-google-find-urls","Sitemaps Help Google Find URLs",[16,6185,6186],{},"A sitemap gives Google a structured list of URLs you consider important.",[16,6188,2065],{},[168,6190,6192],{"className":5253,"code":6191,"language":5255,"meta":173,"style":173},"\u003Curl>\n  \u003Cloc>https:\u002F\u002Fexample.com\u002Fblog\u002Fnew-article\u003C\u002Floc>\n  \u003Clastmod>2026-09-20\u003C\u002Flastmod>\n\u003C\u002Furl>\n",[20,6193,6194,6198,6203,6208],{"__ignoreMap":173},[177,6195,6196],{"class":179,"line":180},[177,6197,5262],{},[177,6199,6200],{"class":179,"line":215},[177,6201,6202],{},"  \u003Cloc>https:\u002F\u002Fexample.com\u002Fblog\u002Fnew-article\u003C\u002Floc>\n",[177,6204,6205],{"class":179,"line":224},[177,6206,6207],{},"  \u003Clastmod>2026-09-20\u003C\u002Flastmod>\n",[177,6209,6210],{"class":179,"line":235},[177,6211,5272],{},[16,6213,6214,6215,52],{},"Google describes sitemaps as an important discovery mechanism, particularly for large websites, recently launched sites, sites with few external links, and sites containing specialized media or news content. (",[46,6216,4087],{"href":6217,"rel":6218},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fsitemaps\u002Foverview?authuser=1&utm_source=chatgpt.com",[50],[16,6220,6221],{},"A sitemap is especially useful when a page is not likely to be discovered quickly through normal link crawling.",[16,6223,6224,6225,6227],{},"However, submitting a sitemap does ",[28,6226,3050],{}," mean:",[1573,6229,6230],{},[16,6231,6232],{},"“Google must crawl and index every URL listed here.”",[16,6234,6235,6236,6238,6239,52],{},"Google explicitly describes sitemap submission as a ",[28,6237,5278],{},". It does not guarantee that Google will download, crawl, or index every submitted URL. (",[46,6240,4087],{"href":5289,"rel":6241},[50],[16,6243,6244],{},"Sitemaps should therefore complement good internal linking rather than replace it.",[16,6246,6247],{},[177,6248,5295],{},[11,6250,6252],{"id":6251},"discovery-is-not-crawling","Discovery Is Not Crawling",[16,6254,6255],{},"This distinction causes a large amount of SEO confusion.",[16,6257,6258],{},"Suppose Google finds:",[168,6260,6263],{"className":6261,"code":6262,"language":787,"meta":173},[785],"https:\u002F\u002Fexample.com\u002Fnew-page\n",[20,6264,6262],{"__ignoreMap":173},[16,6266,6267],{},"through an internal link.",[16,6269,6270,6271,59],{},"At this point Google may know the URL exists. That is ",[28,6272,6273],{},"discovery",[16,6275,6276,6277,59],{},"Googlebot may later fetch the URL. That is ",[28,6278,4981],{},[16,6280,6281,6282,578,6285,52],{},"Google may then analyze the content and decide whether and how to store it in its search index. That is ",[28,6283,6284],{},"indexing",[46,6286,4087],{"href":2372,"rel":6287},[50],[16,6289,6290],{},"A simplified flow looks like this:",[168,6292,6295],{"className":6293,"code":6294,"language":787,"meta":173},[785],"URL discovered\n      ↓\nAdded to crawling process\n      ↓\nGooglebot fetches the URL\n      ↓\nContent is processed\u002Frendered\n      ↓\nGoogle evaluates it for indexing\n",[20,6296,6294],{"__ignoreMap":173},[16,6298,6299],{},"Not every URL moves through every step.",[16,6301,6302,6303,52],{},"Google explicitly states that following its technical requirements does not guarantee crawling, indexing, or appearance in Search. (",[46,6304,4087],{"href":2372,"rel":6305},[50],[11,6307,6309],{"id":6308},"robotstxt-does-not-hide-a-url","robots.txt Does Not Hide a URL",[16,6311,6312,6313,6315],{},"A common misconception is that blocking a URL in ",[20,6314,2010],{}," prevents Google from discovering it.",[16,6317,6318],{},"That is not necessarily true.",[16,6320,6321,6322,6324],{},"If another page links to the blocked URL, Google may still learn that the URL exists. A ",[20,6323,2010],{}," rule prevents the specified crawler from fetching the blocked resource; it does not necessarily erase knowledge of the URL.",[16,6326,6327,6328,52],{},"Google notes that a blocked URL may even appear in search results without a snippet because Google cannot crawl its content. (",[46,6329,4087],{"href":6330,"rel":6331},"https:\u002F\u002Fdevelopers.google.com\u002Fcrawling\u002Fdocs\u002Frobots-txt\u002Frobots-txt-spec?authuser=117&utm_source=chatgpt.com",[50],[16,6333,6334,6335,6337,6338,52],{},"If your goal is to prevent indexing, Google recommends using ",[20,6336,5362],{}," while allowing the crawler to access the page so it can see that directive. (",[46,6339,4087],{"href":5427,"rel":6340},[50],[16,6342,6343],{},[177,6344,5433],{},[11,6346,6348],{"id":6347},"what-about-nofollow","What About nofollow?",[16,6350,6351],{},"A link using:",[168,6353,6355],{"className":4213,"code":6354,"language":4215,"meta":173,"style":173},"\u003Ca href=\"\u002Fprivate-page\" rel=\"nofollow\">Page\u003C\u002Fa>\n",[20,6356,6357],{"__ignoreMap":173},[177,6358,6359,6361,6363,6365,6367,6370,6373,6375,6378,6381,6383],{"class":179,"line":180},[177,6360,4222],{"class":183},[177,6362,46],{"class":4225},[177,6364,5139],{"class":187},[177,6366,4234],{"class":183},[177,6368,6369],{"class":194},"\"\u002Fprivate-page\"",[177,6371,6372],{"class":187}," rel",[177,6374,4234],{"class":183},[177,6376,6377],{"class":194},"\"nofollow\"",[177,6379,6380],{"class":183},">Page\u003C\u002F",[177,6382,46],{"class":4225},[177,6384,4272],{"class":183},[16,6386,6387],{},"generally tells Google not to follow that particular link.",[16,6389,6390,6391,52],{},"However, this does not guarantee that the destination URL remains undiscovered. Google may find the same URL through another internal link, another website, or a sitemap. (",[46,6392,4087],{"href":6393,"rel":6394},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fqualify-outbound-links?utm_source=chatgpt.com",[50],[16,6396,6397],{},"Discovery is therefore best understood as a web-wide process rather than something controlled by a single link.",[11,6399,6401],{"id":6400},"search-console-and-url-submission","Search Console and URL Submission",[16,6403,6404],{},"For a small number of pages you manage, Google Search Console's URL Inspection tool can be used to request crawling.",[16,6406,6407,6408,52],{},"For larger groups of URLs, Google recommends using a sitemap. (",[46,6409,4087],{"href":6410,"rel":6411},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fask-google-to-recrawl?utm_source=chatgpt.com",[50],[16,6413,6414,6415,52],{},"Repeatedly requesting indexing does not make Google crawl the same URL faster, and a crawl request does not guarantee inclusion in search results. (",[46,6416,4087],{"href":6410,"rel":6417},[50],[16,6419,6420,6421,6424,6425,6428,6429,6432,6433,578,6436,52],{},"Another common misconception involves Google's ",[28,6422,6423],{},"Indexing API",". It is not a general-purpose API for submitting ordinary pages. Google currently documents it for pages containing ",[20,6426,6427],{},"JobPosting"," or livestream ",[20,6430,6431],{},"BroadcastEvent"," content embedded in ",[20,6434,6435],{},"VideoObject",[46,6437,4087],{"href":6438,"rel":6439},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fapis\u002Findexing-api\u002Fv3\u002Fusing-api?utm_source=chatgpt.com",[50],[11,6441,6443],{"id":6442},"improve-url-discovery","Improve URL Discovery",[16,6445,6446],{},"For most websites, the practical approach is straightforward:",[1745,6448,6449,6452,6455,6461,6464,6467,6473,6476],{},[382,6450,6451],{},"Give every important page a permanent, crawlable URL.",[382,6453,6454],{},"Link to new pages from existing relevant pages.",[382,6456,6457,6458,6460],{},"Use normal ",[20,6459,5999],{}," links.",[382,6462,6463],{},"Keep important pages reachable through your site architecture.",[382,6465,6466],{},"Maintain an accurate sitemap containing URLs you want Google to find.",[382,6468,6469,6470,6472],{},"Update meaningful ",[20,6471,2157],{}," values when content actually changes.",[382,6474,6475],{},"Avoid accidentally blocking required pages or resources.",[382,6477,6478],{},"Use Search Console to diagnose important URLs that are not being discovered or crawled.",[16,6480,6481,6482,52],{},"Google also warns that discovery may be slower if important links available on desktop are missing from the mobile version of a site, because Google indexes the mobile version of pages. (",[46,6483,4087],{"href":6484,"rel":6485},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Ftroubleshoot-crawling-errors?authuser=2&utm_source=chatgpt.com",[50],[11,6487,899],{"id":898},[16,6489,6490,6491,2165,6494,59],{},"Treat ",[28,6492,6493],{},"internal links as the primary discovery architecture",[28,6495,6496],{},"sitemaps as a complementary discovery signal",[16,6498,6499],{},"A new page should ideally be discoverable naturally from another useful page rather than existing only inside a sitemap. For large or frequently updated websites, automate sitemap generation and ensure newly published canonical URLs enter the sitemap promptly.",[16,6501,6502],{},"If an important page is not appearing in Google, diagnose the stages separately:",[168,6504,6507],{"className":6505,"code":6506,"language":787,"meta":173},[785],"Does Google know the URL?\n        ↓\nCan Google crawl it?\n        ↓\nCan Google render the content?\n        ↓\nIs it eligible for indexing?\n        ↓\nDid Google choose to index it?\n",[20,6508,6506],{"__ignoreMap":173},[16,6510,6511],{},"Trying to solve an indexing problem by repeatedly submitting the URL will not help if the underlying problem is actually site architecture, crawlability, rendering, duplication, or content quality.",[11,6513,919],{"id":918},[921,6515,6517],{"id":6516},"how-long-does-google-take-to-discover-a-new-url","How long does Google take to discover a new URL?",[16,6519,6520,6521,52],{},"There is no guaranteed discovery time. Google says crawling after a request can take from a few days to a few weeks, and its crawling schedule is algorithmic. (",[46,6522,4087],{"href":6410,"rel":6523},[50],[921,6525,6527],{"id":6526},"does-google-need-a-sitemap-to-discover-pages","Does Google need a sitemap to discover pages?",[16,6529,6530,6531,52],{},"No. If your pages are properly linked, Google can usually discover most of them through links. Sitemaps become particularly useful for large, new, complex, or media-heavy sites. (",[46,6532,4087],{"href":6217,"rel":6533},[50],[921,6535,6537],{"id":6536},"can-google-discover-a-page-with-no-internal-links","Can Google discover a page with no internal links?",[16,6539,6540],{},"Potentially. It might discover the URL through an external link, sitemap, or another source. But relying on that is poor site architecture for an important page.",[921,6542,6544],{"id":6543},"does-sitemap-submission-guarantee-indexing","Does sitemap submission guarantee indexing?",[16,6546,6547,6548,52],{},"No. Google explicitly says sitemap submission is a hint and does not guarantee crawling or indexing. (",[46,6549,4087],{"href":5289,"rel":6550},[50],[921,6552,6554],{"id":6553},"does-robotstxt-stop-url-discovery","Does robots.txt stop URL discovery?",[16,6556,6557,6558,52],{},"Not necessarily. Google may know a blocked URL from links or other discovery mechanisms even when it cannot crawl the page. (",[46,6559,4087],{"href":6330,"rel":6560},[50],[11,6562,952],{"id":951},[16,6564,6565],{},"Google cannot crawl a page it does not know exists.",[16,6567,6568],{},"New URLs are primarily discovered as Googlebot follows crawlable links across the web and processes sitemaps provided by site owners. Once discovered, a URL enters a separate process in which Google decides whether and when to crawl it, then whether the resulting content should be indexed.",[16,6570,6571,6572],{},"For SEO, the practical lesson is simple: ",[28,6573,6574],{},"publish URLs into a discoverable web structure, not merely onto a server.",[11,6576,980],{"id":979},[379,6578,6579,6591,6602,6614,6624,6635,6647,6658],{},[382,6580,2365,6581,578,6584,205,6587],{},[987,6582,6583],{},"In-depth guide to how Google Search works",[46,6585,4087],{"href":2372,"rel":6586},[50],[46,6588,6590],{"href":2372,"rel":6589},[50],"Google documentation",[382,6592,2365,6593,578,6596,205,6599],{},[987,6594,6595],{},"Link best practices for Google",[46,6597,4087],{"href":6074,"rel":6598},[50],[46,6600,6590],{"href":5165,"rel":6601},[50],[382,6603,2365,6604,578,6607,205,6610],{},[987,6605,6606],{},"Learn about sitemaps",[46,6608,4087],{"href":6217,"rel":6609},[50],[46,6611,6590],{"href":6612,"rel":6613},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fsitemaps\u002Foverview?utm_source=chatgpt.com",[50],[382,6615,2365,6616,578,6618,205,6621],{},[987,6617,2419],{},[46,6619,4087],{"href":5289,"rel":6620},[50],[46,6622,6590],{"href":2422,"rel":6623},[50],[382,6625,2365,6626,578,6629,205,6632],{},[987,6627,6628],{},"Ask Google to recrawl your URLs",[46,6630,4087],{"href":6410,"rel":6631},[50],[46,6633,6590],{"href":6410,"rel":6634},[50],[382,6636,2365,6637,578,6640,205,6644],{},[987,6638,6639],{},"Understand JavaScript SEO basics",[46,6641,4087],{"href":6642,"rel":6643},"https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fjavascript\u002Fjavascript-seo-basics?utm_source=chatgpt.com",[50],[46,6645,6590],{"href":6642,"rel":6646},[50],[382,6648,6649,6650,578,6652,205,6655],{},"Google Crawling Infrastructure — ",[987,6651,2429],{},[46,6653,4087],{"href":6330,"rel":6654},[50],[46,6656,6590],{"href":2432,"rel":6657},[50],[382,6659,2365,6660,578,6663,205,6666],{},[987,6661,6662],{},"Using the Indexing API",[46,6664,4087],{"href":6438,"rel":6665},[50],[46,6667,6590],{"href":6438,"rel":6668},[50],[1086,6670,5833],{},{"title":173,"searchDepth":215,"depth":215,"links":6672},[6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687],{"id":5872,"depth":215,"text":5873},{"id":40,"depth":215,"text":41},{"id":5917,"depth":215,"text":5918},{"id":6020,"depth":215,"text":6021},{"id":6090,"depth":215,"text":6091},{"id":6182,"depth":215,"text":6183},{"id":6251,"depth":215,"text":6252},{"id":6308,"depth":215,"text":6309},{"id":6347,"depth":215,"text":6348},{"id":6400,"depth":215,"text":6401},{"id":6442,"depth":215,"text":6443},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Learn how Google discovers new URLs through links, sitemaps, redirects and crawling, and why URL discovery does not automatically mean indexing.","\u002Fdiscovers-in-urls.png","Google Discovers New URLs",{},"\u002Fblog\u002Fen\u002Fdiscovers-urls",{"title":5867,"description":6688},"discovers-urls","blog\u002Fen\u002Fdiscovers-urls","discovers-new-urls",1599,"9xgNoG_xA-rgZ_r3op-TMw2koAVAJkquXL2s6dVmED4",{"id":6700,"title":6701,"author":6,"body":6702,"category":1104,"description":7907,"draft":1106,"extension":1107,"featured":280,"image":7908,"imageAlt":7909,"locale":1110,"meta":7910,"navigation":280,"path":7911,"publishedAt":4961,"readingTime":271,"seo":7912,"slug":7913,"stem":7914,"translationKey":7913,"updatedAt":4961,"wordCount":7915,"__hash__":7916},"blog\u002Fblog\u002Fen\u002Fdocker-production.md","Docker for Production Web Applications: Practical Guide",{"type":8,"value":6703,"toc":7885},[6704,6708,6715,6718,6720,6723,6726,6730,6823,6827,6830,6838,6841,7024,7027,7038,7042,7045,7054,7057,7060,7069,7075,7080,7084,7087,7101,7112,7115,7119,7122,7133,7136,7163,7170,7176,7180,7187,7190,7246,7249,7252,7256,7263,7266,7273,7276,7281,7286,7289,7294,7298,7301,7321,7328,7339,7342,7357,7374,7377,7381,7384,7386,7409,7416,7419,7439,7442,7447,7451,7466,7469,7480,7483,7487,7490,7651,7670,7674,7681,7688,7692,7695,7698,7701,7706,7708,7711,7714,7719,7722,7725,7727,7731,7734,7738,7747,7754,7760,7764,7767,7775,7778,7780,7783,7786,7788,7882],[11,6705,6707],{"id":6706},"docker-for-production-web-applications","Docker for Production Web Applications",[16,6709,6710,6711,6714],{},"Docker can run production web applications reliably, but ",[20,6712,6713],{},"docker compose up -d"," is not, by itself, a production strategy. The difficult part is not starting containers. It is making sure those containers can be rebuilt predictably, survive failures, avoid exposing unnecessary privileges, preserve important data, stay within resource limits, produce usable logs, and be replaced safely during deployments.",[16,6716,6717],{},"For a small or medium web application on a single server, Docker Compose can be a perfectly reasonable production deployment model. Docker explicitly documents Compose for single-host production deployments. As infrastructure grows across multiple machines, however, scheduling, failover, service discovery, rolling deployments, and orchestration become separate architectural concerns.",[11,6719,41],{"id":40},[16,6721,6722],{},"Docker is suitable for production when containers are treated as disposable runtime units rather than miniature servers. Build immutable images, run applications with the least privilege they require, persist state outside the container layer, configure health checks and restart behavior, constrain CPU and memory, rotate or export logs, protect secrets, expose only necessary ports, and maintain tested backup and deployment procedures.",[16,6724,6725],{},"Docker provides most of these primitives. Production reliability comes from configuring them correctly.",[11,6727,6729],{"id":6728},"production-essentials","Production Essentials",[65,6731,6732,6741],{},[68,6733,6734],{},[71,6735,6736,6738],{},[74,6737,3348],{},[74,6739,6740],{},"Production expectation",[84,6742,6743,6751,6759,6767,6775,6783,6791,6799,6807,6815],{},[71,6744,6745,6748],{},[89,6746,6747],{},"Images",[89,6749,6750],{},"Reproducible, minimal and tested",[71,6752,6753,6756],{},[89,6754,6755],{},"Application",[89,6757,6758],{},"Stateless where practical",[71,6760,6761,6764],{},[89,6762,6763],{},"Security",[89,6765,6766],{},"Non-root, least privilege, controlled Docker access",[71,6768,6769,6772],{},[89,6770,6771],{},"Resources",[89,6773,6774],{},"CPU and memory limits",[71,6776,6777,6780],{},[89,6778,6779],{},"Networking",[89,6781,6782],{},"Only necessary ports exposed",[71,6784,6785,6788],{},[89,6786,6787],{},"State",[89,6789,6790],{},"Persistent volumes or external managed services",[71,6792,6793,6796],{},[89,6794,6795],{},"Reliability",[89,6797,6798],{},"Health checks and restart policies",[71,6800,6801,6804],{},[89,6802,6803],{},"Logs",[89,6805,6806],{},"Rotation or external aggregation",[71,6808,6809,6812],{},[89,6810,6811],{},"Secrets",[89,6813,6814],{},"Kept outside image layers",[71,6816,6817,6820],{},[89,6818,6819],{},"Deployment",[89,6821,6822],{},"Repeatable build, deploy and rollback process",[11,6824,6826],{"id":6825},"build-production-images","Build Production Images",[16,6828,6829],{},"A production image should contain what the application needs to run, not everything that was required to build it.",[16,6831,6832,6833,52],{},"Docker recommends multi-stage builds for separating compilers, development dependencies and build tooling from the final runtime image. Smaller runtime images generally contain fewer unnecessary dependencies and reduce the available attack surface. Docker also recommends trusted, minimal base images and periodically rebuilding images so updated dependencies can be incorporated. (",[46,6834,6837],{"href":6835,"rel":6836},"https:\u002F\u002Fdocs.docker.com\u002Fbuild\u002Fbuilding\u002Fbest-practices\u002F?utm_source=chatgpt.com",[50],"docs.docker.com",[16,6839,6840],{},"A typical pattern looks like this:",[168,6842,6846],{"className":6843,"code":6844,"language":6845,"meta":173,"style":173},"language-dockerfile shiki shiki-themes github-light github-dark","# syntax=docker\u002Fdockerfile:1\n\nFROM node:24-alpine AS build\n\nWORKDIR \u002Fapp\n\nCOPY package*.json .\u002F\nRUN npm ci\n\nCOPY . .\nRUN npm run build\n\n\nFROM node:24-alpine AS runtime\n\nWORKDIR \u002Fapp\n\nENV NODE_ENV=production\n\nCOPY package*.json .\u002F\nRUN npm ci --omit=dev && npm cache clean --force\n\nCOPY --from=build \u002Fapp\u002Fdist .\u002Fdist\n\nUSER node\n\nEXPOSE 3000\n\nHEALTHCHECK --interval=30s \\\n  --timeout=3s \\\n  --start-period=10s \\\n  --retries=3 \\\n  CMD wget -qO- http:\u002F\u002F127.0.0.1:3000\u002Fhealth || exit 1\n\nCMD [\"node\", \"dist\u002Fserver.js\"]\n","dockerfile",[20,6847,6848,6853,6857,6862,6866,6871,6875,6880,6885,6889,6894,6899,6903,6907,6912,6916,6920,6924,6929,6934,6939,6945,6950,6956,6961,6967,6972,6978,6983,6989,6995,7001,7007,7013,7018],{"__ignoreMap":173},[177,6849,6850],{"class":179,"line":180},[177,6851,6852],{},"# syntax=docker\u002Fdockerfile:1\n",[177,6854,6855],{"class":179,"line":215},[177,6856,281],{"emptyLinePlaceholder":280},[177,6858,6859],{"class":179,"line":224},[177,6860,6861],{},"FROM node:24-alpine AS build\n",[177,6863,6864],{"class":179,"line":235},[177,6865,281],{"emptyLinePlaceholder":280},[177,6867,6868],{"class":179,"line":241},[177,6869,6870],{},"WORKDIR \u002Fapp\n",[177,6872,6873],{"class":179,"line":247},[177,6874,281],{"emptyLinePlaceholder":280},[177,6876,6877],{"class":179,"line":253},[177,6878,6879],{},"COPY package*.json .\u002F\n",[177,6881,6882],{"class":179,"line":259},[177,6883,6884],{},"RUN npm ci\n",[177,6886,6887],{"class":179,"line":265},[177,6888,281],{"emptyLinePlaceholder":280},[177,6890,6891],{"class":179,"line":271},[177,6892,6893],{},"COPY . .\n",[177,6895,6896],{"class":179,"line":277},[177,6897,6898],{},"RUN npm run build\n",[177,6900,6901],{"class":179,"line":284},[177,6902,281],{"emptyLinePlaceholder":280},[177,6904,6905],{"class":179,"line":306},[177,6906,281],{"emptyLinePlaceholder":280},[177,6908,6909],{"class":179,"line":313},[177,6910,6911],{},"FROM node:24-alpine AS runtime\n",[177,6913,6914],{"class":179,"line":322},[177,6915,281],{"emptyLinePlaceholder":280},[177,6917,6918],{"class":179,"line":334},[177,6919,6870],{},[177,6921,6922],{"class":179,"line":340},[177,6923,281],{"emptyLinePlaceholder":280},[177,6925,6926],{"class":179,"line":345},[177,6927,6928],{},"ENV NODE_ENV=production\n",[177,6930,6932],{"class":179,"line":6931},19,[177,6933,281],{"emptyLinePlaceholder":280},[177,6935,6937],{"class":179,"line":6936},20,[177,6938,6879],{},[177,6940,6942],{"class":179,"line":6941},21,[177,6943,6944],{},"RUN npm ci --omit=dev && npm cache clean --force\n",[177,6946,6948],{"class":179,"line":6947},22,[177,6949,281],{"emptyLinePlaceholder":280},[177,6951,6953],{"class":179,"line":6952},23,[177,6954,6955],{},"COPY --from=build \u002Fapp\u002Fdist .\u002Fdist\n",[177,6957,6959],{"class":179,"line":6958},24,[177,6960,281],{"emptyLinePlaceholder":280},[177,6962,6964],{"class":179,"line":6963},25,[177,6965,6966],{},"USER node\n",[177,6968,6970],{"class":179,"line":6969},26,[177,6971,281],{"emptyLinePlaceholder":280},[177,6973,6975],{"class":179,"line":6974},27,[177,6976,6977],{},"EXPOSE 3000\n",[177,6979,6981],{"class":179,"line":6980},28,[177,6982,281],{"emptyLinePlaceholder":280},[177,6984,6986],{"class":179,"line":6985},29,[177,6987,6988],{},"HEALTHCHECK --interval=30s \\\n",[177,6990,6992],{"class":179,"line":6991},30,[177,6993,6994],{},"  --timeout=3s \\\n",[177,6996,6998],{"class":179,"line":6997},31,[177,6999,7000],{},"  --start-period=10s \\\n",[177,7002,7004],{"class":179,"line":7003},32,[177,7005,7006],{},"  --retries=3 \\\n",[177,7008,7010],{"class":179,"line":7009},33,[177,7011,7012],{},"  CMD wget -qO- http:\u002F\u002F127.0.0.1:3000\u002Fhealth || exit 1\n",[177,7014,7016],{"class":179,"line":7015},34,[177,7017,281],{"emptyLinePlaceholder":280},[177,7019,7021],{"class":179,"line":7020},35,[177,7022,7023],{},"CMD [\"node\", \"dist\u002Fserver.js\"]\n",[16,7025,7026],{},"This is an illustrative Node.js example rather than a universal Dockerfile. The important pattern is the separation between build and runtime stages, installation of production-only dependencies, execution as a non-root user, and an application-level health endpoint.",[16,7028,7029,7030,7033,7034,52],{},"Docker recommends using ",[20,7031,7032],{},"USER"," when a service does not require root privileges. (",[46,7035,6837],{"href":7036,"rel":7037},"https:\u002F\u002Fdocs.docker.com\u002Fbuild\u002Fbuilding\u002Fbest-practices\u002F",[50],[1632,7039,7041],{"id":7040},"pinning-images","Pinning Images",[16,7043,7044],{},"Image tags are mutable. An image such as:",[168,7046,7048],{"className":6843,"code":7047,"language":6845,"meta":173,"style":173},"FROM alpine:3.21\n",[20,7049,7050],{"__ignoreMap":173},[177,7051,7052],{"class":179,"line":180},[177,7053,7047],{},[16,7055,7056],{},"may resolve to a different underlying image after its publisher releases an update.",[16,7058,7059],{},"Docker supports pinning an image by digest:",[168,7061,7063],{"className":6843,"code":7062,"language":6845,"meta":173,"style":173},"FROM alpine:3.21@sha256:...\n",[20,7064,7065],{"__ignoreMap":173},[177,7066,7067],{"class":179,"line":180},[177,7068,7062],{},[16,7070,7071,7072,52],{},"This improves reproducibility because the same digest identifies the same image content. The tradeoff is important: strict digest pinning also means updates do not arrive automatically. A sensible production process combines controlled pinning with automated dependency-update checks rather than permanently freezing old images. (",[46,7073,6837],{"href":7036,"rel":7074},[50],[16,7076,7077],{},[177,7078,7079],{},"INTERNAL LINK: How Docker Images and Layers Work",[11,7081,7083],{"id":7082},"keep-secrets-out","Keep Secrets Out",[16,7085,7086],{},"Passwords, private tokens and credentials should never be baked into an image.",[16,7088,7089,7090,4526,7093,7096,7097,52],{},"Docker specifically warns against using Dockerfile ",[20,7091,7092],{},"ARG",[20,7094,7095],{},"ENV"," for build secrets because those values can persist in the resulting image or its metadata. BuildKit secret mounts make credentials temporarily available during a build without storing them in the final image. (",[46,7098,6837],{"href":7099,"rel":7100},"https:\u002F\u002Fdocs.docker.com\u002Freference\u002Fbuild-checks\u002Fsecrets-used-in-arg-or-env\u002F?utm_source=chatgpt.com",[50],[16,7102,7103,7104,7107,7108,52],{},"Docker Compose also supports runtime secrets. On Linux containers, those secrets can be mounted as files under ",[20,7105,7106],{},"\u002Frun\u002Fsecrets\u002F"," and granted only to services that require them. (",[46,7109,6837],{"href":7110,"rel":7111},"https:\u002F\u002Fdocs.docker.com\u002Fcompose\u002Fhow-tos\u002Fuse-secrets\u002F?utm_source=chatgpt.com",[50],[16,7113,7114],{},"The deeper principle is simple: configuration may change between environments, while the application image should not need to contain the credentials for those environments.",[11,7116,7118],{"id":7117},"limit-container-privileges","Limit Container Privileges",[16,7120,7121],{},"Containers provide isolation, but they are not an excuse to ignore host security.",[16,7123,7124,7125,7128,7129,52],{},"Access to the Docker daemon is especially sensitive. Docker's documentation warns that users capable of controlling the normal rootful Docker daemon can effectively obtain root-level capabilities on the host. Membership in the ",[20,7126,7127],{},"docker"," group therefore needs to be treated as privileged access. (",[46,7130,6837],{"href":7131,"rel":7132},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fsecurity\u002F?utm_source=chatgpt.com",[50],[16,7134,7135],{},"For web applications:",[379,7137,7138,7141,7148,7151,7154,7160],{},[382,7139,7140],{},"run the application as a non-root user when possible;",[382,7142,7143,7144,7147],{},"avoid ",[20,7145,7146],{},"privileged: true",";",[382,7149,7150],{},"drop capabilities the application does not require;",[382,7152,7153],{},"retain Docker's default seccomp protection unless there is a specific, understood reason to change it;",[382,7155,7156,7157,7147],{},"consider ",[20,7158,7159],{},"no-new-privileges",[382,7161,7162],{},"consider Rootless Docker where its operational limitations are acceptable.",[16,7164,7165,7166,52],{},"Docker's rootless mode runs both the daemon and containers without root privileges, reducing the impact of some daemon or runtime vulnerabilities. (",[46,7167,6837],{"href":7168,"rel":7169},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fsecurity\u002Frootless\u002F?utm_source=chatgpt.com",[50],[16,7171,7172,7173,52],{},"Docker also recommends removing unnecessary Linux capabilities rather than adding broad privileges. (",[46,7174,6837],{"href":7131,"rel":7175},[50],[11,7177,7179],{"id":7178},"control-cpu-and-memory","Control CPU and Memory",[16,7181,7182,7183,52],{},"A container has no resource constraints by default. Unless limits are configured, it can consume as much CPU or memory as the host allows. One runaway application can therefore affect other containers running on the same machine. (",[46,7184,6837],{"href":7185,"rel":7186},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fcontainers\u002Fresource_constraints\u002F?utm_source=chatgpt.com",[50],[16,7188,7189],{},"Compose supports controls such as:",[168,7191,7195],{"className":7192,"code":7193,"language":7194,"meta":173,"style":173},"language-yaml shiki shiki-themes github-light github-dark","services:\n  app:\n    image: registry.example.com\u002Fapp:1.4.0\n\n    cpus: 1.0\n    mem_limit: 512m\n","yaml",[20,7196,7197,7205,7212,7222,7226,7236],{"__ignoreMap":173},[177,7198,7199,7202],{"class":179,"line":180},[177,7200,7201],{"class":4225},"services",[177,7203,7204],{"class":183},":\n",[177,7206,7207,7210],{"class":179,"line":215},[177,7208,7209],{"class":4225},"  app",[177,7211,7204],{"class":183},[177,7213,7214,7217,7219],{"class":179,"line":224},[177,7215,7216],{"class":4225},"    image",[177,7218,4296],{"class":183},[177,7220,7221],{"class":194},"registry.example.com\u002Fapp:1.4.0\n",[177,7223,7224],{"class":179,"line":235},[177,7225,281],{"emptyLinePlaceholder":280},[177,7227,7228,7231,7233],{"class":179,"line":241},[177,7229,7230],{"class":4225},"    cpus",[177,7232,4296],{"class":183},[177,7234,7235],{"class":497},"1.0\n",[177,7237,7238,7241,7243],{"class":179,"line":247},[177,7239,7240],{"class":4225},"    mem_limit",[177,7242,4296],{"class":183},[177,7244,7245],{"class":194},"512m\n",[16,7247,7248],{},"Those numbers should not be copied blindly. Measure normal workload, expected traffic, runtime memory behavior and failure conditions first. A PHP-FPM service, JVM application, Node.js process and PostgreSQL server can require very different limits.",[16,7250,7251],{},"The purpose of limits is isolation and predictable failure behavior, not simply making every container use less memory.",[11,7253,7255],{"id":7254},"persist-important-data","Persist Important Data",[16,7257,7258,7259,52],{},"The writable container filesystem is temporary. When the container is removed, data stored only in that writable layer disappears. (",[46,7260,6837],{"href":7261,"rel":7262},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fstorage?utm_source=chatgpt.com",[50],[16,7264,7265],{},"Persistent application data should instead live in Docker volumes, suitable bind mounts, object storage, or external database\u002Fstorage services.",[16,7267,7268,7269,52],{},"Docker describes volumes as its preferred mechanism for persistent container data in many scenarios. Volumes exist independently of an individual container and can be backed up, restored and migrated. (",[46,7270,6837],{"href":7271,"rel":7272},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fstorage\u002Fvolumes\u002F?utm_source=chatgpt.com",[50],[16,7274,7275],{},"That creates an important architectural distinction:",[16,7277,7278],{},[28,7279,7280],{},"Container = replaceable application runtime",[16,7282,7283],{},[28,7284,7285],{},"Volume or external service = persistent state",[16,7287,7288],{},"A volume alone is not a backup. Production systems still need scheduled backups and, more importantly, tested restoration procedures.",[16,7290,7291],{},[177,7292,7293],{},"INTERNAL LINK: Docker Volumes Explained",[11,7295,7297],{"id":7296},"health-and-recovery","Health and Recovery",[16,7299,7300],{},"A process can still be running while the application itself is unusable.",[16,7302,7303,7304,7307,7308,406,7311,2165,7314,578,7317,52],{},"Docker's ",[20,7305,7306],{},"HEALTHCHECK"," instruction allows an image to define a command that tests whether the application is actually functioning. Docker then exposes states such as ",[20,7309,7310],{},"starting",[20,7312,7313],{},"healthy",[20,7315,7316],{},"unhealthy",[46,7318,6837],{"href":7319,"rel":7320},"https:\u002F\u002Fdocs.docker.com\u002Freference\u002Fdockerfile?utm_source=chatgpt.com",[50],[16,7322,7323,7324,7327],{},"For a web service, ",[20,7325,7326],{},"\u002Fhealth"," might verify that the HTTP application can answer requests. More advanced readiness checks may also verify dependencies, although a health endpoint should avoid becoming so complex that a temporary external failure creates unnecessary restart loops.",[16,7329,7330,7331,7334,7335,52],{},"Compose can also wait for a dependency marked ",[20,7332,7333],{},"service_healthy"," before starting another service. (",[46,7336,6837],{"href":7337,"rel":7338},"https:\u002F\u002Fdocs.docker.com\u002Fcompose\u002Fhow-tos\u002Fstartup-order\u002F?utm_source=chatgpt.com",[50],[16,7340,7341],{},"Restart policies solve a related problem:",[168,7343,7345],{"className":7192,"code":7344,"language":7194,"meta":173,"style":173},"restart: unless-stopped\n",[20,7346,7347],{"__ignoreMap":173},[177,7348,7349,7352,7354],{"class":179,"line":180},[177,7350,7351],{"class":4225},"restart",[177,7353,4296],{"class":183},[177,7355,7356],{"class":194},"unless-stopped\n",[16,7358,7359,7360,406,7363,2165,7366,7369,7370,52],{},"Docker documents ",[20,7361,7362],{},"always",[20,7364,7365],{},"unless-stopped",[20,7367,7368],{},"on-failure"," policies for automatically restarting containers after exits or daemon restarts. (",[46,7371,6837],{"href":7372,"rel":7373},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fcontainers\u002Fstart-containers-automatically\u002F?utm_source=chatgpt.com",[50],[16,7375,7376],{},"A restart policy improves recovery from process failure. It does not replace monitoring or fix an application that continuously crashes.",[11,7378,7380],{"id":7379},"control-network-exposure","Control Network Exposure",[16,7382,7383],{},"Published Docker ports require deliberate attention.",[16,7385,2065],{},[168,7387,7391],{"className":7388,"code":7389,"language":7390,"meta":173,"style":173},"language-bash shiki shiki-themes github-light github-dark","docker run -p 3000:3000 myapp\n","bash",[20,7392,7393],{"__ignoreMap":173},[177,7394,7395,7397,7400,7403,7406],{"class":179,"line":180},[177,7396,7127],{"class":187},[177,7398,7399],{"class":194}," run",[177,7401,7402],{"class":497}," -p",[177,7404,7405],{"class":194}," 3000:3000",[177,7407,7408],{"class":194}," myapp\n",[16,7410,7411,7412,52],{},"publishes the port on all host interfaces by default. Docker documentation explicitly notes that such published ports can become externally accessible. (",[46,7413,6837],{"href":7414,"rel":7415},"https:\u002F\u002Fdocs.docker.com\u002Freference\u002Fcli\u002Fdocker\u002Fcontainer\u002Frun?utm_source=chatgpt.com",[50],[16,7417,7418],{},"If a reverse proxy on the same server is the only service that should reach the application, binding to loopback can reduce unnecessary exposure:",[168,7420,7422],{"className":7192,"code":7421,"language":7194,"meta":173,"style":173},"ports:\n  - \"127.0.0.1:3000:3000\"\n",[20,7423,7424,7431],{"__ignoreMap":173},[177,7425,7426,7429],{"class":179,"line":180},[177,7427,7428],{"class":4225},"ports",[177,7430,7204],{"class":183},[177,7432,7433,7436],{"class":179,"line":215},[177,7434,7435],{"class":183},"  - ",[177,7437,7438],{"class":194},"\"127.0.0.1:3000:3000\"\n",[16,7440,7441],{},"Databases, Redis instances and internal queues usually should not be publicly published merely because they run in Docker.",[16,7443,7444],{},[177,7445,7446],{},"INTERNAL LINK: Reverse Proxy Architecture Explained",[11,7448,7450],{"id":7449},"do-not-ignore-logs","Do Not Ignore Logs",[16,7452,7453,7454,7457,7458,7461,7462,52],{},"Docker's default ",[20,7455,7456],{},"json-file"," logging driver does not perform log rotation by default. A noisy application can therefore consume significant disk space over time. Docker recommends considering the ",[20,7459,7460],{},"local"," logging driver to help prevent disk exhaustion. (",[46,7463,6837],{"href":7464,"rel":7465},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Flogging\u002Fconfigure\u002F?utm_source=chatgpt.com",[50],[16,7467,7468],{},"A production setup should deliberately choose between:",[379,7470,7471,7474,7477],{},[382,7472,7473],{},"local logs with rotation;",[382,7475,7476],{},"a logging driver sending logs elsewhere;",[382,7478,7479],{},"an external observability system.",[16,7481,7482],{},"Whatever method is selected, logs should survive long enough to investigate failures without eventually filling the server's disk.",[11,7484,7486],{"id":7485},"a-practical-compose-baseline","A Practical Compose Baseline",[16,7488,7489],{},"A hardened application service might begin with something like:",[168,7491,7493],{"className":7192,"code":7492,"language":7194,"meta":173,"style":173},"services:\n  app:\n    image: registry.example.com\u002Fmyapp:1.4.0\n    restart: unless-stopped\n\n    ports:\n      - \"127.0.0.1:3000:3000\"\n\n    cpus: 1.0\n    mem_limit: 512m\n\n    read_only: true\n\n    tmpfs:\n      - \u002Ftmp\n\n    security_opt:\n      - no-new-privileges:true\n\n    cap_drop:\n      - ALL\n\n    logging:\n      driver: local\n",[20,7494,7495,7501,7507,7516,7525,7529,7536,7543,7547,7555,7563,7567,7576,7580,7587,7594,7598,7605,7612,7616,7623,7630,7634,7641],{"__ignoreMap":173},[177,7496,7497,7499],{"class":179,"line":180},[177,7498,7201],{"class":4225},[177,7500,7204],{"class":183},[177,7502,7503,7505],{"class":179,"line":215},[177,7504,7209],{"class":4225},[177,7506,7204],{"class":183},[177,7508,7509,7511,7513],{"class":179,"line":224},[177,7510,7216],{"class":4225},[177,7512,4296],{"class":183},[177,7514,7515],{"class":194},"registry.example.com\u002Fmyapp:1.4.0\n",[177,7517,7518,7521,7523],{"class":179,"line":235},[177,7519,7520],{"class":4225},"    restart",[177,7522,4296],{"class":183},[177,7524,7356],{"class":194},[177,7526,7527],{"class":179,"line":241},[177,7528,281],{"emptyLinePlaceholder":280},[177,7530,7531,7534],{"class":179,"line":247},[177,7532,7533],{"class":4225},"    ports",[177,7535,7204],{"class":183},[177,7537,7538,7541],{"class":179,"line":253},[177,7539,7540],{"class":183},"      - ",[177,7542,7438],{"class":194},[177,7544,7545],{"class":179,"line":259},[177,7546,281],{"emptyLinePlaceholder":280},[177,7548,7549,7551,7553],{"class":179,"line":265},[177,7550,7230],{"class":4225},[177,7552,4296],{"class":183},[177,7554,7235],{"class":497},[177,7556,7557,7559,7561],{"class":179,"line":271},[177,7558,7240],{"class":4225},[177,7560,4296],{"class":183},[177,7562,7245],{"class":194},[177,7564,7565],{"class":179,"line":277},[177,7566,281],{"emptyLinePlaceholder":280},[177,7568,7569,7572,7574],{"class":179,"line":284},[177,7570,7571],{"class":4225},"    read_only",[177,7573,4296],{"class":183},[177,7575,4719],{"class":497},[177,7577,7578],{"class":179,"line":306},[177,7579,281],{"emptyLinePlaceholder":280},[177,7581,7582,7585],{"class":179,"line":313},[177,7583,7584],{"class":4225},"    tmpfs",[177,7586,7204],{"class":183},[177,7588,7589,7591],{"class":179,"line":322},[177,7590,7540],{"class":183},[177,7592,7593],{"class":194},"\u002Ftmp\n",[177,7595,7596],{"class":179,"line":334},[177,7597,281],{"emptyLinePlaceholder":280},[177,7599,7600,7603],{"class":179,"line":340},[177,7601,7602],{"class":4225},"    security_opt",[177,7604,7204],{"class":183},[177,7606,7607,7609],{"class":179,"line":345},[177,7608,7540],{"class":183},[177,7610,7611],{"class":194},"no-new-privileges:true\n",[177,7613,7614],{"class":179,"line":6931},[177,7615,281],{"emptyLinePlaceholder":280},[177,7617,7618,7621],{"class":179,"line":6936},[177,7619,7620],{"class":4225},"    cap_drop",[177,7622,7204],{"class":183},[177,7624,7625,7627],{"class":179,"line":6941},[177,7626,7540],{"class":183},[177,7628,7629],{"class":194},"ALL\n",[177,7631,7632],{"class":179,"line":6947},[177,7633,281],{"emptyLinePlaceholder":280},[177,7635,7636,7639],{"class":179,"line":6952},[177,7637,7638],{"class":4225},"    logging",[177,7640,7204],{"class":183},[177,7642,7643,7646,7648],{"class":179,"line":6958},[177,7644,7645],{"class":4225},"      driver",[177,7647,4296],{"class":183},[177,7649,7650],{"class":194},"local\n",[16,7652,7653,7654,7657,7658,7661,7662,7665,7666,52],{},"This is a starting point, not a universal template. ",[20,7655,7656],{},"read_only: true"," can break applications that expect writable directories, and dropping every capability can break software that genuinely needs one. Production hardening should therefore follow ",[28,7659,7660],{},"least privilege",", not ",[28,7663,7664],{},"maximum restriction regardless of application behavior",". Compose supports these service-level controls directly. (",[46,7667,6837],{"href":7668,"rel":7669},"https:\u002F\u002Fdocs.docker.com\u002Freference\u002Fcompose-file\u002Fservices\u002F?utm_source=chatgpt.com",[50],[11,7671,7673],{"id":7672},"common-production-mistakes","Common Production Mistakes",[16,7675,7676,7677,7680],{},"The most common Docker production problems are rarely caused by containers themselves. They usually come from deployment choices: running as root unnecessarily, using mutable ",[20,7678,7679],{},"latest"," tags without controlled updates, storing database data inside the container layer, publishing internal ports publicly, having no memory limit, placing credentials in images, allowing logs to grow indefinitely, or treating container restart as a substitute for monitoring.",[16,7682,7683,7684,52],{},"Another common mistake is mounting the application source directory from the host in production. Docker's production Compose guidance specifically suggests removing development-oriented code bind mounts so deployed application code remains inside the image. (",[46,7685,6837],{"href":7686,"rel":7687},"https:\u002F\u002Fdocs.docker.com\u002Fcompose\u002Fhow-tos\u002Fproduction\u002F?utm_source=chatgpt.com",[50],[11,7689,7691],{"id":7690},"when-compose-is-enough","When Compose Is Enough",[16,7693,7694],{},"Docker Compose is a reasonable production option when one host is sufficient and the team can tolerate that host as an infrastructure boundary.",[16,7696,7697],{},"A setup consisting of a reverse proxy, application containers, Redis and perhaps a database can remain operationally simple this way.",[16,7699,7700],{},"The requirements change when you need automatic scheduling across machines, node-level failover, large-scale service discovery, coordinated rolling deployments or extensive horizontal scaling. At that point the question is no longer whether Docker works in production. It is which orchestration platform should manage the containers.",[16,7702,7703],{},[177,7704,7705],{},"INTERNAL LINK: Docker Compose vs Container Orchestration",[11,7707,899],{"id":898},[16,7709,7710],{},"Treat Docker production deployment as a system rather than a Dockerfile.",[16,7712,7713],{},"The minimum useful production model is:",[16,7715,7716],{},[28,7717,7718],{},"source code → CI build and test → immutable image → registry → controlled deployment → health verification → monitoring → rollback",[16,7720,7721],{},"Keep persistent state outside replaceable application containers. Restrict privileges and exposed ports. Define resource limits based on measurement. Protect credentials independently from images. Automate backups and test restores.",[16,7723,7724],{},"Docker simplifies packaging. Production engineering is what makes that package reliable.",[11,7726,919],{"id":918},[921,7728,7730],{"id":7729},"is-docker-compose-safe-for-production","Is Docker Compose safe for production?",[16,7732,7733],{},"It can be. Docker officially documents Compose for production and single-host deployments. Whether it is appropriate depends on the application's availability, scaling and operational requirements.",[921,7735,7737],{"id":7736},"should-containers-run-as-root","Should containers run as root?",[16,7739,7740,7741,7743,7744,52],{},"Only when the application genuinely requires those privileges. Docker recommends using ",[20,7742,7032],{}," for services that can operate without root. (",[46,7745,6837],{"href":7036,"rel":7746},[50],[921,7748,7750,7751,7753],{"id":7749},"should-i-use-latest-in-production","Should I use ",[20,7752,7679],{}," in production?",[16,7755,7756,7757,52],{},"A mutable tag makes exact deployment reproduction harder. Versioned tags or digest pinning provide greater control, provided updates are actively maintained. (",[46,7758,6837],{"href":7036,"rel":7759},[50],[921,7761,7763],{"id":7762},"do-docker-volumes-need-backups","Do Docker volumes need backups?",[16,7765,7766],{},"Yes. Volumes provide persistence outside the container lifecycle; they do not automatically provide disaster recovery.",[921,7768,7770,7771,7774],{"id":7769},"does-restart-always-make-an-application-highly-available","Does ",[20,7772,7773],{},"restart: always"," make an application highly available?",[16,7776,7777],{},"No. It can restart a failed container on the same Docker host. It does not protect against host failure and does not diagnose why the application failed.",[11,7779,952],{"id":951},[16,7781,7782],{},"Docker is not production-ready because a container starts successfully. It becomes part of a production-ready system when images are reproducible, privileges and resources are controlled, state is protected, failures are detectable, logs are managed, network exposure is deliberate, and deployments can be recovered or rolled back.",[16,7784,7785],{},"The container is the replaceable part. The production architecture around it is what provides reliability.",[11,7787,980],{"id":979},[1745,7789,7790,7800,7809,7817,7826,7835,7844,7853,7863,7872],{},[382,7791,7792,7793,1010,7796],{},"Docker — ",[987,7794,7795],{},"Building best practices",[46,7797,7799],{"href":6835,"rel":7798},[50],"Docker Build best practices",[382,7801,7792,7802,1010,7805],{},[987,7803,7804],{},"Use Compose in production",[46,7806,7808],{"href":7686,"rel":7807},[50],"Compose in production",[382,7810,7792,7811,1010,7814],{},[987,7812,7813],{},"Docker Engine security",[46,7815,7813],{"href":7131,"rel":7816},[50],[382,7818,7792,7819,1010,7822],{},[987,7820,7821],{},"Rootless mode",[46,7823,7825],{"href":7168,"rel":7824},[50],"Docker Rootless mode",[382,7827,7792,7828,1010,7831],{},[987,7829,7830],{},"Resource constraints",[46,7832,7834],{"href":7185,"rel":7833},[50],"Docker resource constraints",[382,7836,7792,7837,1010,7840],{},[987,7838,7839],{},"Configure logging drivers",[46,7841,7843],{"href":7464,"rel":7842},[50],"Docker logging drivers",[382,7845,7792,7846,1010,7849],{},[987,7847,7848],{},"Volumes",[46,7850,7852],{"href":7271,"rel":7851},[50],"Docker volumes",[382,7854,7792,7855,1010,7858],{},[987,7856,7857],{},"Build secrets",[46,7859,7862],{"href":7860,"rel":7861},"https:\u002F\u002Fdocs.docker.com\u002Fbuild\u002Fbuilding\u002Fsecrets\u002F?utm_source=chatgpt.com",[50],"Docker build secrets",[382,7864,7792,7865,1010,7868],{},[987,7866,7867],{},"Dockerfile reference",[46,7869,7867],{"href":7870,"rel":7871},"https:\u002F\u002Fdocs.docker.com\u002Freference\u002Fdockerfile\u002F?utm_source=chatgpt.com",[50],[382,7873,7792,7874,1010,7877],{},[987,7875,7876],{},"Port publishing and mapping",[46,7878,7881],{"href":7879,"rel":7880},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fnetwork\u002Fport-publishing\u002F?utm_source=chatgpt.com",[50],"Docker port publishing",[1086,7883,7884],{},"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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":173,"searchDepth":215,"depth":215,"links":7886},[7887,7888,7889,7890,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904,7905,7906],{"id":6706,"depth":215,"text":6707},{"id":40,"depth":215,"text":41},{"id":6728,"depth":215,"text":6729},{"id":6825,"depth":215,"text":6826,"children":7891},[7892],{"id":7040,"depth":224,"text":7041},{"id":7082,"depth":215,"text":7083},{"id":7117,"depth":215,"text":7118},{"id":7178,"depth":215,"text":7179},{"id":7254,"depth":215,"text":7255},{"id":7296,"depth":215,"text":7297},{"id":7379,"depth":215,"text":7380},{"id":7449,"depth":215,"text":7450},{"id":7485,"depth":215,"text":7486},{"id":7672,"depth":215,"text":7673},{"id":7690,"depth":215,"text":7691},{"id":898,"depth":215,"text":899},{"id":918,"depth":215,"text":919},{"id":951,"depth":215,"text":952},{"id":979,"depth":215,"text":980},"Learn how to run Docker web applications in production with secure images, resource limits, persistent storage, health checks, logging, secrets and reliable deployment practices.","\u002Fdocker-web.png","Image of Docker",{},"\u002Fblog\u002Fen\u002Fdocker-production",{"title":6701,"description":7907},"docker-production","blog\u002Fen\u002Fdocker-production",1920,"vnDOpZLIoxuAlMoBHLsLlmUDagAj35eyprRE6ByemMQ",1792593776614]