[{"data":1,"prerenderedAt":1210},["ShallowReactive",2],{"page:\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics":3,"all-docs-nav":967},{"id":4,"title":5,"body":6,"breadcrumb":940,"dateModified":950,"datePublished":950,"description":951,"extension":952,"faq":953,"meta":961,"navigation":305,"path":962,"seo":963,"slug":12,"stem":964,"type":965,"__hash__":966},"content\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics\u002Findex.md","Profiling Hugo Templates With Template Metrics",{"type":7,"value":8,"toc":920},"minimark",[9,13,17,30,35,59,63,91,99,102,133,275,279,282,319,326,330,337,357,360,364,375,395,398,492,496,499,502,579,582,586,589,614,621,699,703,706,758,766,770,818,822,832,836,841,847,851,857,861,864,868,871,875,878,882,916],[10,11,5],"h1",{"id":12},"profiling-hugo-templates-with-template-metrics",[14,15,16],"p",{},"Hugo is fast enough that a slow Hugo build is almost always a specific template doing something expensive once per page. The problem is that \"the build takes 41 seconds\" gives you nowhere to start, and the usual instinct — reduce the number of pages — is both hard and unnecessary.",[14,18,19,23,24,29],{},[20,21,22],"code",{},"hugo --templateMetrics"," answers the question directly: which templates ran, how often, how long they took in total, and how many of those executions were served from cache. This guide reads that report, shows the three patterns it usually reveals, and measures the result on a 4,000-page site. It is part of ",[25,26,28],"a",{"href":27},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002F","Hugo Build Times for Large Repositories",".",[31,32,34],"h2",{"id":33},"prerequisites","Prerequisites",[36,37,38,46,49],"ul",{},[39,40,41,42,45],"li",{},"Hugo 0.120 or newer (",[20,43,44],{},"hugo version","); the metrics output has been stable for several releases.",[39,47,48],{},"A build slow enough to care about — under ten seconds, this exercise is usually not worth it.",[39,50,51,54,55,58],{},[20,52,53],{},"hyperfine"," or ",[20,56,57],{},"time"," for measuring real build durations with instrumentation off.",[31,60,62],{"id":61},"read-the-report","Read the Report",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-bash shiki shiki-themes github-light github-dark","hugo --templateMetrics --templateMetricsHints --quiet\n","bash","",[20,71,72],{"__ignoreMap":69},[73,74,77,81,85,88],"span",{"class":75,"line":76},"line",1,[73,78,80],{"class":79},"sScJk","hugo",[73,82,84],{"class":83},"sj4cs"," --templateMetrics",[73,86,87],{"class":83}," --templateMetricsHints",[73,89,90],{"class":83}," --quiet\n",[64,92,97],{"className":93,"code":95,"language":96,"meta":69},[94],"language-text","Template Metrics:\n\n     cumulative       average       maximum      cache  percent  cached  total\n       duration      duration      duration  potential                  count  template\n     ----------     ---------     ---------  ---------  -------  ------  -----  --------\n      18.412s        4.60ms       31.2ms          92%     44.9       0    4001  partials\u002Frelated-pages.html\n       9.884s        2.47ms       11.9ms          88%     24.1       0    4001  partials\u002Fsidebar-tree.html\n       4.201s        1.05ms        6.4ms           0%     10.2       0    4001  partials\u002Fhead.html\n       2.930s        0.73ms        4.1ms          71%      7.1       0    4001  partials\u002Fbreadcrumbs.html\n       1.612s        0.40ms        2.2ms         100%      3.9       0    4001  partials\u002Ffooter-nav.html\n","text",[20,98,95],{"__ignoreMap":69},[14,100,101],{},"Four columns decide what to do:",[36,103,104,111,117,127],{},[39,105,106,110],{},[107,108,109],"strong",{},"cumulative duration"," — the only column that ranks work correctly. Sort by it and fix from the top.",[39,112,113,116],{},[107,114,115],{},"total count"," — a count equal to your page count means \"runs once per page\".",[39,118,119,122,123,126],{},[107,120,121],{},"cached"," — executions served by ",[20,124,125],{},"partialCached",". Zero here with a high count is the opportunity.",[39,128,129,132],{},[107,130,131],{},"cache potential"," — Hugo's own hint about how much of this template's output looks identical across executions.",[134,135,136,271],"figure",{},[137,138,145,146,145,150,145,154,145,161],"svg",{"viewBox":139,"role":140,"ariaLabelledBy":141,"xmlns":144},"0 0 760 300","img",[142,143],"tm-read-title","tm-read-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[147,148,149],"title",{"id":142},"How to read the template metrics columns",[151,152,153],"desc",{"id":143},"A breakdown of a metrics row. Cumulative duration of 18.4 seconds ranks the template first. Average duration of 4.6 milliseconds looks harmless on its own. Total count of 4,001 equals the page count, meaning it runs once per page. Cache potential of 92 percent and cached count of zero together identify the opportunity.",[155,156],"rect",{"x":157,"y":157,"width":158,"height":159,"fill":160},"0","760","300","#ffffff",[162,163,165,166,165,173,165,184,165,190,165,195,165,201,165,206,165,210,165,213,165,216,165,222,165,225,165,228,165,231,165,237,165,240,165,243,165,246,165,253,165,258,165,262,165,267,145],"g",{"style":164},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[96,167,172],{"x":168,"y":169,"fill":170,"style":171},"380","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","One row, four signals",[155,174],{"x":175,"y":176,"width":177,"height":178,"rx":179,"fill":180,"opacity":181,"stroke":182,"style":183},"40","56","160","70","10","#ff595e","0.16","#d83b41","stroke-width:1.5px",[96,185,189],{"x":186,"y":187,"fill":170,"style":188},"120","82","font-size:12px;font-weight:700;text-anchor:middle","cumulative",[96,191,194],{"x":186,"y":192,"fill":170,"style":193},"102","font-size:13px;font-weight:700;text-anchor:middle","18.412s",[96,196,200],{"x":186,"y":197,"fill":198,"style":199},"119","#556071","font-size:11px;text-anchor:middle","rank by this",[155,202],{"x":203,"y":176,"width":177,"height":178,"rx":179,"fill":204,"opacity":205,"stroke":198,"style":183},"215","#d9e2ef","0.5",[96,207,209],{"x":208,"y":187,"fill":170,"style":188},"295","average",[96,211,212],{"x":208,"y":192,"fill":170,"style":193},"4.60ms",[96,214,215],{"x":208,"y":197,"fill":198,"style":199},"looks harmless",[155,217],{"x":218,"y":176,"width":177,"height":178,"rx":179,"fill":219,"opacity":220,"stroke":221,"style":183},"390","#ffca3a","0.3","#a97b00",[96,223,115],{"x":224,"y":187,"fill":170,"style":188},"470",[96,226,227],{"x":224,"y":192,"fill":170,"style":193},"4,001",[96,229,230],{"x":224,"y":197,"fill":198,"style":199},"= one per page",[155,232],{"x":233,"y":176,"width":177,"height":178,"rx":179,"fill":234,"opacity":235,"stroke":236,"style":183},"565","#8ac926","0.18","#5a8a16",[96,238,131],{"x":239,"y":187,"fill":170,"style":188},"645",[96,241,242],{"x":239,"y":192,"fill":170,"style":193},"92% · 0 cached",[96,244,245],{"x":239,"y":197,"fill":198,"style":199},"the opportunity",[155,247],{"x":175,"y":248,"width":249,"height":250,"rx":179,"fill":251,"opacity":252,"stroke":251,"style":183},"164","685","52","#6a4c93","0.12",[96,254,257],{"x":255,"y":256,"fill":170,"style":188},"382","186","Reading: this partial renders once per page, 92% of that output never varies, and none of it is cached",[96,259,261],{"x":255,"y":260,"fill":198,"style":199},"206","Expected saving from partialCached: roughly 0.92 × 18.4 s ≈ 17 s",[96,263,266],{"x":175,"y":264,"fill":198,"style":265},"258","font-size:11px","Absolute times are inflated by instrumentation — compare rows within a run, not across runs",[96,268,270],{"x":175,"y":269,"fill":198,"style":265},"280","Measure the real improvement afterwards with the flag off",[272,273,274],"figcaption",{},"Average duration is the number people quote and the least useful one. A partial averaging under five milliseconds was 45% of this build.",[31,276,278],{"id":277},"pattern-1-a-partial-that-should-be-cached","Pattern 1 — A Partial That Should Be Cached",[14,280,281],{},"The top row above is the archetype: a \"related pages\" partial that scans site pages to build a list. Its output varies by section, not by page, so it can be cached with the section as the key:",[64,283,287],{"className":284,"code":285,"language":286,"meta":69,"style":69},"language-go-html-template shiki shiki-themes github-light github-dark","{{\u002F* before — runs the scan once per page *\u002F}}\n{{ partial \"related-pages.html\" . }}\n\n{{\u002F* after — one execution per section, reused for every page in it *\u002F}}\n{{ partialCached \"related-pages.html\" . .Section }}\n","go-html-template",[20,288,289,294,300,307,313],{"__ignoreMap":69},[73,290,291],{"class":75,"line":76},[73,292,293],{},"{{\u002F* before — runs the scan once per page *\u002F}}\n",[73,295,297],{"class":75,"line":296},2,[73,298,299],{},"{{ partial \"related-pages.html\" . }}\n",[73,301,303],{"class":75,"line":302},3,[73,304,306],{"emptyLinePlaceholder":305},true,"\n",[73,308,310],{"class":75,"line":309},4,[73,311,312],{},"{{\u002F* after — one execution per section, reused for every page in it *\u002F}}\n",[73,314,316],{"class":75,"line":315},5,[73,317,318],{},"{{ partialCached \"related-pages.html\" . .Section }}\n",[14,320,321,322,325],{},"The variant key is the whole discipline here. ",[20,323,324],{},"partialCached \"x\" ."," with no key caches one result for the entire site, which is correct only when the output is genuinely global — a footer, a nav bar. Any per-section or per-type variation must appear in the key, or pages get another section's content, which is a much worse bug than a slow build.",[31,327,329],{"id":328},"pattern-2-a-scan-that-should-be-a-lookup","Pattern 2 — A Scan That Should Be a Lookup",[14,331,332,333,336],{},"The second row, a sidebar tree, is usually a different problem: it iterates ",[20,334,335],{},".Site.RegularPages"," per page to build a hierarchy. Caching helps, but the real fix is to compute the structure once and look it up:",[64,338,340],{"className":284,"code":339,"language":286,"meta":69,"style":69},"{{\u002F* Build the map once, in a cached partial that returns a dict *\u002F}}\n{{ $tree := partialCached \"build-tree.html\" . \"site-tree\" }}\n{{ $branch := index $tree .Section }}\n",[20,341,342,347,352],{"__ignoreMap":69},[73,343,344],{"class":75,"line":76},[73,345,346],{},"{{\u002F* Build the map once, in a cached partial that returns a dict *\u002F}}\n",[73,348,349],{"class":75,"line":296},[73,350,351],{},"{{ $tree := partialCached \"build-tree.html\" . \"site-tree\" }}\n",[73,353,354],{"class":75,"line":302},[73,355,356],{},"{{ $branch := index $tree .Section }}\n",[14,358,359],{},"A scan is O(pages) per page, which is O(pages²) per build — the reason a site that was fine at 400 pages becomes unbearable at 4,000. Turning the scan into one map build plus a lookup is what changes the shape of the curve rather than its constant.",[31,361,363],{"id":362},"pattern-3-expensive-work-per-page-that-nobody-needs","Pattern 3 — Expensive Work Per Page That Nobody Needs",[14,365,366,367,370,371,374],{},"The third row, ",[20,368,369],{},"head.html"," at 0% cache potential, is genuinely per-page — it emits the title and canonical for each page. But partials like this often accumulate work that does not need to be there: a resource fingerprint recomputed per page, a date formatted three different ways, a ",[20,372,373],{},"where"," clause over all pages to decide whether to show a banner.",[64,376,378],{"className":284,"code":377,"language":286,"meta":69,"style":69},"{{\u002F* Fingerprint once for the whole site, not once per page *\u002F}}\n{{ $css := resources.Get \"css\u002Fmain.css\" | minify | fingerprint }}   {{\u002F* hoisted *\u002F}}\n\u003Clink rel=\"stylesheet\" href=\"{{ $css.RelPermalink }}\" integrity=\"{{ $css.Data.Integrity }}\">\n",[20,379,380,385,390],{"__ignoreMap":69},[73,381,382],{"class":75,"line":76},[73,383,384],{},"{{\u002F* Fingerprint once for the whole site, not once per page *\u002F}}\n",[73,386,387],{"class":75,"line":296},[73,388,389],{},"{{ $css := resources.Get \"css\u002Fmain.css\" | minify | fingerprint }}   {{\u002F* hoisted *\u002F}}\n",[73,391,392],{"class":75,"line":302},[73,393,394],{},"\u003Clink rel=\"stylesheet\" href=\"{{ $css.RelPermalink }}\" integrity=\"{{ $css.Data.Integrity }}\">\n",[14,396,397],{},"Hugo caches resource pipelines internally, so the second call is cheap — but the surrounding template logic is not, and moving invariant work out of a per-page partial is free speed.",[134,399,400,489],{},[137,401,145,406,145,409,145,412,145,415],{"viewBox":402,"role":140,"ariaLabelledBy":403,"xmlns":144},"0 0 760 290",[404,405],"tm-fix-title","tm-fix-desc",[147,407,408],{"id":404},"Three fixes and what each is worth",[151,410,411],{"id":405},"Three patterns with their savings on a 4,000-page build. Caching the related-pages partial saves 17 seconds. Replacing the sidebar scan with a lookup saves 9 seconds. Hoisting invariant work out of the head partial saves 3 seconds. Total build time falls from 41 seconds to 6 seconds.",[155,413],{"x":157,"y":157,"width":158,"height":414,"fill":160},"290",[162,416,165,417,165,421,165,426,165,431,165,435,165,441,165,445,165,449,165,453,165,458,165,463,165,467,165,470,165,475,165,480,165,485,145],{"style":164},[96,418,420],{"x":168,"y":419,"fill":170,"style":171},"26","41 s → 6 s, three changes, no content removed",[75,422],{"x1":423,"y1":424,"x2":423,"y2":425,"stroke":204,"style":183},"250","44","212",[96,427,125],{"x":428,"y":429,"fill":170,"style":430},"60","80","font-size:12px;font-weight:700",[96,432,434],{"x":428,"y":433,"fill":198,"style":265},"96","related-pages",[155,436],{"x":423,"y":437,"width":168,"height":438,"rx":439,"fill":234,"opacity":440,"stroke":236,"style":183},"62","30","5","0.24",[96,442,444],{"x":443,"y":187,"fill":236,"style":188},"440","−17 s",[96,446,448],{"x":428,"y":447,"fill":170,"style":430},"140","scan → lookup",[96,450,452],{"x":428,"y":451,"fill":198,"style":265},"156","sidebar-tree",[155,454],{"x":423,"y":455,"width":456,"height":438,"rx":439,"fill":234,"opacity":457,"stroke":236,"style":183},"122","201","0.2",[96,459,462],{"x":460,"y":461,"fill":236,"style":188},"350","142","−9 s",[96,464,466],{"x":428,"y":465,"fill":170,"style":430},"200","hoist invariants",[96,468,369],{"x":428,"y":469,"fill":198,"style":265},"216",[155,471],{"x":423,"y":472,"width":473,"height":438,"rx":439,"fill":219,"opacity":474,"stroke":221,"style":183},"182","67","0.34",[96,476,479],{"x":477,"y":478,"fill":221,"style":430},"345","202","−3 s",[96,481,484],{"x":482,"y":483,"fill":198,"style":265},"237","252","Shared linear scale · 4,000 pages, hyperfine 10 runs, warm module cache, metrics off",[96,486,488],{"x":423,"y":487,"fill":198,"style":265},"274","Remaining 6 s is markdown rendering and file I\u002FO — the floor for this corpus",[272,490,491],{},"The ordering matters: fixing the top row first meant the second measurement was taken on a build where it was no longer the dominant cost, which is how you avoid optimising something that stopped mattering.",[31,493,495],{"id":494},"why-scans-dominate-at-scale","Why Scans Dominate at Scale",[14,497,498],{},"The middle fix is the one worth understanding rather than copying, because it explains why build times get worse suddenly rather than gradually.",[14,500,501],{},"A template that iterates every page, executed once per page, does page-count squared units of work. At 400 pages that is 160,000 operations — invisible. At 4,000 pages it is 16 million, and the build that took four seconds now takes forty. Nothing changed except the corpus, which is why teams experience this as \"Hugo got slow\" rather than as a template they wrote three years ago.",[134,503,504,576],{},[137,505,145,509,145,512,145,515,145,517],{"viewBox":402,"role":140,"ariaLabelledBy":506,"xmlns":144},[507,508],"tm-scale-title","tm-scale-desc",[147,510,511],{"id":507},"Per-page scan versus one-time map build as a site grows",[151,513,514],{"id":508},"Two curves against page count. The per-page scan grows quadratically: 1.2 seconds at 500 pages, 5 seconds at 1,000, 20 seconds at 2,000 and 41 seconds at 4,000. The map-plus-lookup approach grows linearly and stays under 7 seconds across the same range.",[155,516],{"x":157,"y":157,"width":158,"height":414,"fill":160},[162,518,165,519,165,522,165,525,165,528,165,533,165,537,165,543,165,547,165,552,165,556,165,561,165,564,165,568,165,572,145],{"style":164},[96,520,521],{"x":168,"y":419,"fill":170,"style":171},"The curve, not the constant",[75,523],{"x1":524,"y1":250,"x2":524,"y2":425,"stroke":198,"style":183},"100",[75,526],{"x1":524,"y1":425,"x2":527,"y2":425,"stroke":198,"style":183},"700",[96,529,532],{"x":530,"y":531,"fill":198,"style":265},"54","58","45 s",[96,534,536],{"x":535,"y":469,"fill":198,"style":265},"72","0 s",[538,539],"polyline",{"points":540,"fill":541,"stroke":182,"style":542},"150,208 300,194 450,141 640,66","none","stroke-width:2.5px",[538,544],{"points":545,"fill":541,"stroke":236,"style":546},"150,210 300,207 450,203 640,197","stroke-width:2.5px;stroke-dasharray:7 5",[96,548,551],{"x":549,"y":531,"fill":182,"style":550},"560","font-size:11px;font-weight:700","per-page scan · 41 s",[96,553,555],{"x":549,"y":554,"fill":236,"style":550},"190","map + lookup · 6 s",[96,557,560],{"x":558,"y":559,"fill":198,"style":199},"150","234","500",[96,562,563],{"x":159,"y":559,"fill":198,"style":199},"1,000",[96,565,567],{"x":566,"y":559,"fill":198,"style":199},"450","2,000",[96,569,571],{"x":570,"y":559,"fill":198,"style":199},"640","4,000 pages",[96,573,575],{"x":524,"y":574,"fill":198,"style":265},"266","Same templates, same machine · the only variable is how many pages the corpus contains",[272,577,578],{},"A site that doubles its content and quadruples its build time has a quadratic template somewhere. The metrics report finds it in one run.",[14,580,581],{},"The tell in the report is a partial whose cumulative duration grows faster than the page count between two profiles taken months apart. If you keep the metrics output from a release — even pasted into a commit message — that comparison takes seconds.",[31,583,585],{"id":584},"verify-with-real-timings","Verify With Real Timings",[14,587,588],{},"Instrumentation inflates absolute numbers, so measure the actual improvement with the flag off:",[64,590,592],{"className":66,"code":591,"language":68,"meta":69,"style":69},"hyperfine --warmup 1 --runs 10 'hugo --gc --minify --cleanDestinationDir'\n",[20,593,594],{"__ignoreMap":69},[73,595,596,598,601,604,607,610],{"class":75,"line":76},[73,597,53],{"class":79},[73,599,600],{"class":83}," --warmup",[73,602,603],{"class":83}," 1",[73,605,606],{"class":83}," --runs",[73,608,609],{"class":83}," 10",[73,611,613],{"class":612},"sZZnC"," 'hugo --gc --minify --cleanDestinationDir'\n",[14,615,616,617,620],{},"Re-run ",[20,618,619],{},"--templateMetrics"," after each change to re-rank; the second-worst template is frequently not what it was, because caching one partial removes work from another's measured time.",[622,623,624,640],"table",{},[625,626,627],"thead",{},[628,629,630,634,637],"tr",{},[631,632,633],"th",{},"Stage",[631,635,636],{},"Build time",[631,638,639],{},"Top template by cumulative",[641,642,643,658,675,688],"tbody",{},[628,644,645,649,652],{},[646,647,648],"td",{},"Baseline",[646,650,651],{},"41.0 s",[646,653,654,657],{},[20,655,656],{},"related-pages.html"," — 18.4 s",[628,659,660,666,669],{},[646,661,662,663,665],{},"+ ",[20,664,125],{}," on related pages",[646,667,668],{},"23.6 s",[646,670,671,674],{},[20,672,673],{},"sidebar-tree.html"," — 9.9 s",[628,676,677,680,683],{},[646,678,679],{},"+ tree scan → lookup",[646,681,682],{},"9.1 s",[646,684,685,687],{},[20,686,369],{}," — 4.2 s",[628,689,690,693,696],{},[646,691,692],{},"+ hoisted invariants in head",[646,694,695],{},"6.2 s",[646,697,698],{},"markdown rendering (not a template)",[31,700,702],{"id":701},"keep-the-profile-in-the-repository","Keep the Profile in the Repository",[14,704,705],{},"A profile taken once is a fix; a profile taken every release is a guard. Save the metrics output as a build artifact and print the top five rows in the CI log, so a template that starts creeping is visible in a pull request rather than in a complaint six months later.",[64,707,709],{"className":66,"code":708,"language":68,"meta":69,"style":69},"hugo --templateMetrics --quiet 2>&1 | sed -n '\u002FTemplate Metrics\u002F,\u002F^$\u002Fp' | head -12 \\\n  | tee build-profile.txt\n",[20,710,711,747],{"__ignoreMap":69},[73,712,713,715,717,720,724,727,730,733,736,738,741,744],{"class":75,"line":76},[73,714,80],{"class":79},[73,716,84],{"class":83},[73,718,719],{"class":83}," --quiet",[73,721,723],{"class":722},"szBVR"," 2>&1",[73,725,726],{"class":722}," |",[73,728,729],{"class":79}," sed",[73,731,732],{"class":83}," -n",[73,734,735],{"class":612}," '\u002FTemplate Metrics\u002F,\u002F^$\u002Fp'",[73,737,726],{"class":722},[73,739,740],{"class":79}," head",[73,742,743],{"class":83}," -12",[73,745,746],{"class":83}," \\\n",[73,748,749,752,755],{"class":75,"line":296},[73,750,751],{"class":722},"  |",[73,753,754],{"class":79}," tee",[73,756,757],{"class":612}," build-profile.txt\n",[14,759,760,761,765],{},"The cheapest useful assertion is a ceiling on the top row's cumulative duration. It is deliberately loose — the point is not to police milliseconds but to catch the change that adds a per-page scan, which shows up as a doubling rather than a few per cent. Pair it with the wall-clock budget from ",[25,762,764],{"href":763},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fmeasuring-build-time-regressions-in-ci\u002F","Measuring Build-Time Regressions in CI",", and between them you know both that the build got slower and which template did it.",[31,767,769],{"id":768},"pitfalls-rollback","Pitfalls & Rollback",[36,771,772,781,787,793,799,805],{},[39,773,774,777,778,780],{},[107,775,776],{},"Caching with the wrong key."," ",[20,779,125],{}," without a variant key on per-section output serves the wrong section's content. Always pass the discriminator.",[39,782,783,786],{},[107,784,785],{},"Optimising by average duration."," The report sorts by cumulative for a reason; a 0.4 ms partial can be seconds of build.",[39,788,789,792],{},[107,790,791],{},"Trusting instrumented absolute times."," They are inflated. Compare rows within a run and measure real times separately.",[39,794,795,798],{},[107,796,797],{},"Re-running the profile only once."," After each fix the ranking changes; a second profile costs one build and prevents wasted work.",[39,800,801,804],{},[107,802,803],{},"Caching something that must vary."," If in doubt, verify a handful of pages in the output rather than assuming — a wrong-content bug is silent.",[39,806,807,810,811,813,814,817],{},[107,808,809],{},"Rollback:"," every change here is one template line. Reverting a ",[20,812,125],{}," to a ",[20,815,816],{},"partial"," restores previous behaviour immediately, with no cache to clear beyond the build directory.",[31,819,821],{"id":820},"conclusion","Conclusion",[14,823,824,825,827,828,29],{},"A slow Hugo build has a name, and ",[20,826,619],{}," tells you what it is in one run. Rank by cumulative duration, look for a high count with zero cached executions, and apply the three standard fixes — cache what does not vary, turn scans into lookups, and hoist invariant work out of per-page partials. Re-profile after each change, and confirm with real timings that instrumentation is not exaggerating. Combine this with the caching and hook strategies in ",[25,829,831],{"href":830},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fspeeding-up-hugo-builds-with-render-hooks-and-caching\u002F","Speeding Up Hugo Builds With Render Hooks and Caching",[31,833,835],{"id":834},"faq","FAQ",[837,838,840],"h3",{"id":839},"what-does-the-cached-column-in-template-metrics-mean","What does the cached column in template metrics mean?",[14,842,843,844,846],{},"It counts executions served from ",[20,845,125],{}," rather than re-rendered. A partial with a high count and zero cached entries is running once per page, which is the main thing the report exists to reveal.",[837,848,850],{"id":849},"should-i-cache-every-partial","Should I cache every partial?",[14,852,853,854,856],{},"No. ",[20,855,125],{}," is only correct when the output does not vary per page, or varies only by a key you can express. Caching a partial whose output depends on the current page produces wrong pages, which is far worse than a slow build.",[837,858,860],{"id":859},"why-is-my-average-duration-tiny-but-the-build-slow","Why is my average duration tiny but the build slow?",[14,862,863],{},"Because cumulative duration is what matters. A partial averaging 0.4 milliseconds across 4,000 pages is 1.6 seconds of build time; the report sorts by cumulative precisely so that small-but-frequent work is visible.",[837,865,867],{"id":866},"does-templatemetrics-slow-the-build-down","Does templateMetrics slow the build down?",[14,869,870],{},"Yes, measurably — instrumentation adds overhead, and the reported absolute times are inflated. Use it to compare templates against each other within one run, and measure real build times separately with the flag off.",[837,872,874],{"id":873},"what-if-the-slow-template-is-a-shortcode","What if the slow template is a shortcode?",[14,876,877],{},"Shortcodes appear in the report like any other template. A shortcode executed hundreds of times per build is a common cause, and the same caching and simplification advice applies.",[31,879,881],{"id":880},"related","Related",[36,883,884,892,897,904,911],{},[39,885,886,777,889,891],{},[107,887,888],{},"Parent:",[25,890,28],{"href":27}," — the wider build-speed picture.",[39,893,894,896],{},[25,895,831],{"href":830}," — the caching layers beyond templates.",[39,898,899,903],{},[25,900,902],{"href":901},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhow-to-benchmark-hugo-vs-astro-build-speeds\u002F","How to Benchmark Hugo vs Astro Build Speeds"," — measuring builds honestly.",[39,905,906,910],{},[25,907,909],{"href":908},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions\u002F","Caching Hugo Builds in GitHub Actions"," — keeping the gains in CI.",[39,912,913,915],{},[25,914,764],{"href":763}," — stopping the 41 seconds from coming back.",[917,918,919],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .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}",{"title":69,"searchDepth":296,"depth":296,"links":921},[922,923,924,925,926,927,928,929,930,931,932,939],{"id":33,"depth":296,"text":34},{"id":61,"depth":296,"text":62},{"id":277,"depth":296,"text":278},{"id":328,"depth":296,"text":329},{"id":362,"depth":296,"text":363},{"id":494,"depth":296,"text":495},{"id":584,"depth":296,"text":585},{"id":701,"depth":296,"text":702},{"id":768,"depth":296,"text":769},{"id":820,"depth":296,"text":821},{"id":834,"depth":296,"text":835,"children":933},[934,935,936,937,938],{"id":839,"depth":302,"text":840},{"id":849,"depth":302,"text":850},{"id":859,"depth":302,"text":860},{"id":866,"depth":302,"text":867},{"id":873,"depth":302,"text":874},{"id":880,"depth":296,"text":881},[941,944,947,948],{"name":942,"item":943},"Home","\u002F",{"name":945,"item":946},"Choosing the Right Static Site Generator for Production","\u002Fchoosing-the-right-static-site-generator-for-production\u002F",{"name":28,"item":27},{"name":5,"item":949},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics\u002F","2026-08-01","Use hugo --templateMetrics to find which partial is eating your build: read cumulative duration, spot cache misses, and cut a 41 s build to 6 s on 4,000 pages.","md",[954,956,958,959,960],{"q":840,"a":955},"It counts executions served from partialCached rather than re-rendered. A partial with a high count and zero cached entries is running once per page, which is the main thing the report exists to reveal.",{"q":850,"a":957},"No. partialCached is only correct when the output does not vary per page, or varies only by a key you can express. Caching a partial whose output depends on the current page produces wrong pages, which is far worse than a slow build.",{"q":860,"a":863},{"q":867,"a":870},{"q":874,"a":877},{},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics",{"title":5,"description":951},"choosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics\u002Findex","article","KdGfTymGORFrQU4k7GTvrCL3duwY1ZQQxgiOozdoNYE",[968,971,974,977,979,981,982,985,987,990,993,996,999,1002,1005,1008,1011,1014,1017,1020,1023,1026,1029,1032,1035,1038,1041,1044,1047,1050,1053,1056,1059,1062,1065,1068,1071,1074,1077,1080,1083,1086,1089,1092,1095,1098,1101,1104,1107,1110,1113,1116,1119,1122,1125,1128,1131,1134,1137,1140,1143,1146,1149,1152,1155,1158,1161,1163,1166,1169,1171,1174,1177,1180,1183,1186,1189,1192,1195,1198,1201,1204,1207],{"path":969,"title":970},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fchoosing-between-astro-and-eleventy-for-large-docs","Astro vs Eleventy for Large Docs (1000+ Pages)",{"path":972,"title":973},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fcontent-collections-vs-eleventy-data-cascade","Content Collections vs the Eleventy Data Cascade",{"path":975,"title":976},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":978,"title":902},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhow-to-benchmark-hugo-vs-astro-build-speeds",{"path":980,"title":28},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories",{"path":962,"title":5},{"path":983,"title":984},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fspeeding-up-hugo-builds-with-render-hooks-and-caching","Speeding Up Hugo Builds with Render Hooks & Caching",{"path":986,"title":945},"\u002Fchoosing-the-right-static-site-generator-for-production",{"path":988,"title":989},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Feleventy-vs-jekyll-for-markdown-heavy-blogs","Eleventy vs Jekyll for Markdown-Heavy Blogs",{"path":991,"title":992},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem","Jekyll Plugin Ecosystem",{"path":994,"title":995},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Freplacing-jekyll-plugins-when-migrating-to-eleventy","Replacing Jekyll Plugins When Migrating to Eleventy",{"path":997,"title":998},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Frunning-jekyll-on-github-pages-without-plugins","Running Jekyll on GitHub Pages Without Plugins",{"path":1000,"title":1001},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":1003,"title":1004},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration","Keeping Redirects Working After an SSG Migration",{"path":1006,"title":1007},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo","Migrating a Docs Site From Jekyll to Hugo",{"path":1009,"title":1010},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-hugo-to-astro-without-breaking-urls","Migrating From Hugo to Astro Without Breaking URLs",{"path":1012,"title":1013},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fporting-shortcodes-and-includes-between-generators","Porting Shortcodes and Includes Between Generators",{"path":1015,"title":1016},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fhandling-dynamic-routes-in-nextjs-static-export","Handling Dynamic Routes in Next.js Static Export",{"path":1018,"title":1019},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":1021,"title":1022},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fmigrating-from-gatsby-to-nextjs-static-export","Migrating from Gatsby to Next.js Static Export",{"path":1024,"title":1025},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-static-export-vs-astro-for-marketing-sites","Next.js Static Export vs Astro for Marketing",{"path":1027,"title":1028},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fbest-ssg-for-technical-writers-without-coding-experience","Best SSG for Non-Developer Technical Writers",{"path":1030,"title":1031},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation","Choosing an SSG for API Reference Documentation",{"path":1033,"title":1034},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":1036,"title":1037},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fpicking-an-ssg-for-a-multi-language-documentation-site","Picking an SSG for a Multi-Language Docs Site",{"path":1039,"title":1040},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams","SSG Selection Checklist for Engineering Teams",{"path":1042,"title":1043},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":1045,"title":1046},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fpurging-the-cdn-cache-after-a-static-deploy","Purging the CDN Cache After a Static Deploy",{"path":1048,"title":1049},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fsetting-cache-control-headers-on-cloudflare-pages","Cache-Control Headers on Cloudflare Pages",{"path":1051,"title":1052},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fsetting-up-proper-cache-headers-on-netlify","Proper Cache Headers on Netlify for SSGs",{"path":1054,"title":1055},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Feliminating-layout-shift-from-web-fonts","Eliminating Layout Shift From Web Fonts",{"path":1057,"title":1058},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-late-loading-embeds","Fixing CLS From Late-Loading Embeds",{"path":1060,"title":1061},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":1063,"title":1064},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Fmeasuring-cls-in-the-field-with-web-vitals-js","Measuring CLS in the Field With web-vitals.js",{"path":1066,"title":1067},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Freserving-space-for-images-and-embeds-to-stop-layout-shift","Reserving Space for Images and Embeds",{"path":1069,"title":1070},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":1072,"title":1073},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fself-hosting-google-fonts-to-eliminate-layout-shift","Self-Host Google Fonts to Eliminate Layout Shift",{"path":1075,"title":1076},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fsubsetting-variable-fonts-for-faster-first-render","Subsetting Variable Fonts for Faster First Render",{"path":1078,"title":1079},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fbuilding-an-image-cdn-pipeline-for-static-sites","Building an Image CDN Pipeline for Static Sites",{"path":1081,"title":1082},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":1084,"title":1085},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Foptimizing-webp-images-in-hugo-without-plugins","Optimizing WebP Images in Hugo Without Plugins",{"path":1087,"title":1088},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fserving-avif-with-fallbacks-on-static-sites","Serving AVIF With Fallbacks on Static Sites",{"path":1090,"title":1091},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":1093,"title":1094},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":1096,"title":1097},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fhow-to-reduce-bundle-size-in-eleventy-builds","How to Reduce Bundle Size in Eleventy Builds",{"path":1099,"title":1100},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":1102,"title":1103},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fmeasuring-inp-on-static-sites-with-real-user-monitoring","Measuring INP on Static Sites with RUM",{"path":1105,"title":1106},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Feliminating-render-blocking-css-on-static-sites","Eliminating Render-Blocking CSS on Static Sites",{"path":1108,"title":1109},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":1111,"title":1112},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Foptimizing-lcp-on-astro-with-priority-hints","Optimizing LCP on Astro with Priority Hints",{"path":1114,"title":1115},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Freducing-lcp-from-hero-images-on-static-sites","Reducing LCP from Hero Images on Static Sites",{"path":1117,"title":1118},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fauditing-third-party-scripts-with-lighthouse","Auditing Third-Party Scripts With Lighthouse",{"path":1120,"title":1121},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":1123,"title":1124},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites","Lazy-Loading YouTube Embeds on Static Sites",{"path":1126,"title":1127},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fself-hosting-analytics-to-cut-third-party-requests","Self-Hosting Analytics to Cut Third-Party Requests",{"path":1129,"title":1130},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":1132,"title":1133},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fdeploying-hugo-to-cloudflare-pages-and-workers","Deploying Hugo to Cloudflare Pages and Workers",{"path":1135,"title":1136},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":1138,"title":1139},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers","Docs-as-Code Review Workflow for Writers",{"path":1141,"title":1142},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":1144,"title":1145},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fscheduling-content-publication-with-cron-triggered-builds","Scheduling Content Publication With Cron-Triggered Builds",{"path":1147,"title":1148},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fwiring-a-headless-cms-to-a-static-build","Wiring a Headless CMS to a Static Build",{"path":1150,"title":1151},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fcaching-node-modules-in-github-actions-for-faster-ssg-builds","Caching node_modules in GitHub Actions",{"path":1153,"title":1154},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-multiple-environments-from-one-workflow","Deploying to Multiple Environments From One Workflow",{"path":1156,"title":1157},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fhow-to-set-up-github-actions-for-hugo-deployments","GitHub Actions for Hugo Deployments",{"path":1159,"title":1160},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":1162,"title":909},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions",{"path":1164,"title":1165},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":1167,"title":1168},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":1170,"title":764},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fmeasuring-build-time-regressions-in-ci",{"path":1172,"title":1173},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fsharing-build-cache-across-ci-runners","Sharing Build Cache Across CI Runners",{"path":1175,"title":1176},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":1178,"title":1179},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":1181,"title":1182},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":1184,"title":1185},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fsetting-up-deploy-previews-on-netlify-for-every-pull-request","Netlify Deploy Previews for Every Pull Request",{"path":1187,"title":1188},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fvercel-isr-vs-static-generation-for-ssgs","Vercel ISR vs Static Generation for SSGs",{"path":1190,"title":1191},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fautomating-preview-deploy-pipelines-with-github-actions","Automating Preview Deploy Pipelines with GitHub Actions",{"path":1193,"title":1194},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":1196,"title":1197},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":1199,"title":1200},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":1202,"title":1203},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":1205,"title":1206},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frolling-back-a-bad-static-deploy-in-under-a-minute","Rolling Back a Bad Static Deploy in Under a Minute",{"path":1208,"title":1209},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frunning-smoke-tests-against-a-preview-url","Running Smoke Tests Against a Preview URL",1785611671049]