[{"data":1,"prerenderedAt":4651},["ShallowReactive",2],{"navigation_docs":3,"-quayel-gateway-plugins-cache":91,"-quayel-gateway-plugins-cache-surround":4646},[4],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":90},"Quayel Gateway","i-lucide-network","\u002Fquayel-gateway","quayel-gateway",[10,29,68],{"title":11,"icon":12,"path":13,"stem":14,"children":15},"Getting Started","i-lucide-rocket","\u002Fquayel-gateway\u002Fgetting-started","quayel-gateway\u002F01.getting-started\u002Findex",[16,19,24],{"title":17,"path":13,"stem":14,"icon":18},"Introduction","i-lucide-book-open",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fquayel-gateway\u002Fgetting-started\u002Finstallation","quayel-gateway\u002F01.getting-started\u002F1.installation","i-lucide-container",{"title":25,"path":26,"stem":27,"icon":28},"Project Structure","\u002Fquayel-gateway\u002Fgetting-started\u002Fproject-structure","quayel-gateway\u002F01.getting-started\u002F2.project-structure","i-lucide-folder-tree",{"title":30,"icon":31,"path":32,"stem":33,"children":34},"Plugins","i-lucide-puzzle","\u002Fquayel-gateway\u002Fplugins","quayel-gateway\u002F02.plugins\u002Findex",[35,38,43,48,53,58,63],{"title":36,"path":32,"stem":33,"icon":37},"Overview","i-lucide-workflow",{"title":39,"path":40,"stem":41,"icon":42},"IP Intelligence","\u002Fquayel-gateway\u002Fplugins\u002Fip-intel","quayel-gateway\u002F02.plugins\u002F1.ip-intel","i-lucide-radar",{"title":44,"path":45,"stem":46,"icon":47},"Firewall","\u002Fquayel-gateway\u002Fplugins\u002Ffirewall","quayel-gateway\u002F02.plugins\u002F2.firewall","i-lucide-shield",{"title":49,"path":50,"stem":51,"icon":52},"Rate Limiting","\u002Fquayel-gateway\u002Fplugins\u002Frate-limiting","quayel-gateway\u002F02.plugins\u002F3.rate-limiting","i-lucide-gauge",{"title":54,"path":55,"stem":56,"icon":57},"Cache","\u002Fquayel-gateway\u002Fplugins\u002Fcache","quayel-gateway\u002F02.plugins\u002F4.cache","i-lucide-database",{"title":59,"path":60,"stem":61,"icon":62},"Load Balancer","\u002Fquayel-gateway\u002Fplugins\u002Fload-balancer","quayel-gateway\u002F02.plugins\u002F5.load-balancer","i-lucide-scale",{"title":64,"path":65,"stem":66,"icon":67},"Auto-SSL","\u002Fquayel-gateway\u002Fplugins\u002Fauto-ssl","quayel-gateway\u002F02.plugins\u002F6.auto-ssl","i-lucide-lock",{"title":69,"icon":70,"path":71,"stem":72,"children":73},"AI","i-lucide-bot","\u002Fquayel-gateway\u002Fai","quayel-gateway\u002F03.ai\u002Findex",[74,75,80,85],{"title":36,"path":71,"stem":72,"icon":70},{"title":76,"path":77,"stem":78,"icon":79},"The Quayel Gateway Skill","\u002Fquayel-gateway\u002Fai\u002Fskill","quayel-gateway\u002F03.ai\u002F1.skill","i-lucide-wand-sparkles",{"title":81,"path":82,"stem":83,"icon":84},"Installing the Skill","\u002Fquayel-gateway\u002Fai\u002Finstallation","quayel-gateway\u002F03.ai\u002F2.installation","i-lucide-download",{"title":86,"path":87,"stem":88,"icon":89},"AI Agent Guide","\u002Fquayel-gateway\u002Fai\u002Fagent-guide","quayel-gateway\u002F03.ai\u002F3.agent-guide","i-lucide-braces",false,{"id":92,"title":54,"body":93,"description":4639,"extension":4640,"links":4641,"meta":4642,"navigation":4643,"path":55,"seo":4644,"stem":56,"__hash__":4645},"docs\u002Fquayel-gateway\u002F02.plugins\u002F4.cache.md",{"type":94,"value":95,"toc":4577},"minimark",[96,101,110,115,644,648,847,851,855,858,893,897,900,1002,1006,1009,1013,1022,1068,1085,1089,1092,1151,1155,1166,1170,1176,1321,1325,1330,1338,1342,1387,1393,1397,1400,1473,1477,1483,1487,1549,1559,1563,1570,1574,1580,1584,1589,1595,1605,1609,1615,1622,1626,1632,1640,1644,1723,1727,1740,1746,1749,1753,1758,1762,1768,1772,1796,1800,1806,1822,1826,1829,1846,1849,1853,1859,1863,1866,1911,1914,1918,1963,1966,1969,2028,2032,2036,2042,2087,2090,2093,2178,2184,2188,2197,2259,2262,2268,2272,2406,2410,2420,2426,2430,2435,2527,2531,2536,2555,2560,2585,2589,2593,2868,2872,3230,3234,3367,3371,3630,3633,3642,3645,3658,3666,3670,4147,4151,4236,4240,4434,4438,4441,4469,4473,4540,4544,4573],[97,98,100],"h1",{"id":99},"cache-plugin","Cache Plugin",[102,103,104,105,109],"p",{},"The cache plugin stores and serves responses at the edge, reducing upstream load and improving latency. It supports TTL-based expiration, bypass modes, custom cache keys, and ",[106,107,108],"strong",{},"singleflight revalidation"," to prevent cache stampedes.",[111,112,114],"h2",{"id":113},"configuration","Configuration",[116,117,122],"pre",{"className":118,"code":119,"language":120,"meta":121,"style":121},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"plugins\": {\n    \"cache\": {\n      \"enabled\": true,\n      \"max_object_size_bytes\": 10485760,\n      \"rules\": [\n        {\n          \"id\": \"cache-static\",\n          \"name\": \"Cache Static Assets\",\n          \"enabled\": true,\n          \"conditions\": [\n            {\n              \"left\": \"req.path\",\n              \"operator\": \"regex\",\n              \"value\": \"\\\\.(css|js|png|jpg|svg|woff2?)$\"\n            }\n          ],\n          \"cache\": \"eligible\",\n          \"edge_ttl\": {\n            \"mode\": \"custom\",\n            \"seconds\": 3600\n          },\n          \"browser_ttl\": {\n            \"mode\": \"custom\",\n            \"seconds\": 300\n          },\n          \"cache_key\": {\n            \"mode\": \"default\"\n          },\n          \"statuses\": [200, 301, 404],\n          \"stale_while_revalidate\": 30,\n          \"stale_if_error\": 120\n        }\n      ]\n    }\n  }\n}\n","json","",[123,124,125,134,153,169,186,204,219,225,250,271,284,298,304,327,348,372,378,384,404,418,440,455,461,475,494,508,513,527,545,550,582,599,614,620,626,632,638],"code",{"__ignoreMap":121},[126,127,130],"span",{"class":128,"line":129},"line",1,[126,131,133],{"class":132},"sMK4o","{\n",[126,135,137,140,144,147,150],{"class":128,"line":136},2,[126,138,139],{"class":132},"  \"",[126,141,143],{"class":142},"spNyl","plugins",[126,145,146],{"class":132},"\"",[126,148,149],{"class":132},":",[126,151,152],{"class":132}," {\n",[126,154,156,159,163,165,167],{"class":128,"line":155},3,[126,157,158],{"class":132},"    \"",[126,160,162],{"class":161},"sBMFI","cache",[126,164,146],{"class":132},[126,166,149],{"class":132},[126,168,152],{"class":132},[126,170,172,175,179,181,183],{"class":128,"line":171},4,[126,173,174],{"class":132},"      \"",[126,176,178],{"class":177},"sbssI","enabled",[126,180,146],{"class":132},[126,182,149],{"class":132},[126,184,185],{"class":132}," true,\n",[126,187,189,191,194,196,198,201],{"class":128,"line":188},5,[126,190,174],{"class":132},[126,192,193],{"class":177},"max_object_size_bytes",[126,195,146],{"class":132},[126,197,149],{"class":132},[126,199,200],{"class":177}," 10485760",[126,202,203],{"class":132},",\n",[126,205,207,209,212,214,216],{"class":128,"line":206},6,[126,208,174],{"class":132},[126,210,211],{"class":177},"rules",[126,213,146],{"class":132},[126,215,149],{"class":132},[126,217,218],{"class":132}," [\n",[126,220,222],{"class":128,"line":221},7,[126,223,224],{"class":132},"        {\n",[126,226,228,231,235,237,239,242,246,248],{"class":128,"line":227},8,[126,229,230],{"class":132},"          \"",[126,232,234],{"class":233},"swJcz","id",[126,236,146],{"class":132},[126,238,149],{"class":132},[126,240,241],{"class":132}," \"",[126,243,245],{"class":244},"sfazB","cache-static",[126,247,146],{"class":132},[126,249,203],{"class":132},[126,251,253,255,258,260,262,264,267,269],{"class":128,"line":252},9,[126,254,230],{"class":132},[126,256,257],{"class":233},"name",[126,259,146],{"class":132},[126,261,149],{"class":132},[126,263,241],{"class":132},[126,265,266],{"class":244},"Cache Static Assets",[126,268,146],{"class":132},[126,270,203],{"class":132},[126,272,274,276,278,280,282],{"class":128,"line":273},10,[126,275,230],{"class":132},[126,277,178],{"class":233},[126,279,146],{"class":132},[126,281,149],{"class":132},[126,283,185],{"class":132},[126,285,287,289,292,294,296],{"class":128,"line":286},11,[126,288,230],{"class":132},[126,290,291],{"class":233},"conditions",[126,293,146],{"class":132},[126,295,149],{"class":132},[126,297,218],{"class":132},[126,299,301],{"class":128,"line":300},12,[126,302,303],{"class":132},"            {\n",[126,305,307,310,314,316,318,320,323,325],{"class":128,"line":306},13,[126,308,309],{"class":132},"              \"",[126,311,313],{"class":312},"su27w","left",[126,315,146],{"class":132},[126,317,149],{"class":132},[126,319,241],{"class":132},[126,321,322],{"class":244},"req.path",[126,324,146],{"class":132},[126,326,203],{"class":132},[126,328,330,332,335,337,339,341,344,346],{"class":128,"line":329},14,[126,331,309],{"class":132},[126,333,334],{"class":312},"operator",[126,336,146],{"class":132},[126,338,149],{"class":132},[126,340,241],{"class":132},[126,342,343],{"class":244},"regex",[126,345,146],{"class":132},[126,347,203],{"class":132},[126,349,351,353,356,358,360,362,366,369],{"class":128,"line":350},15,[126,352,309],{"class":132},[126,354,355],{"class":312},"value",[126,357,146],{"class":132},[126,359,149],{"class":132},[126,361,241],{"class":132},[126,363,365],{"class":364},"sTEyZ","\\\\",[126,367,368],{"class":244},".(css|js|png|jpg|svg|woff2?)$",[126,370,371],{"class":132},"\"\n",[126,373,375],{"class":128,"line":374},16,[126,376,377],{"class":132},"            }\n",[126,379,381],{"class":128,"line":380},17,[126,382,383],{"class":132},"          ],\n",[126,385,387,389,391,393,395,397,400,402],{"class":128,"line":386},18,[126,388,230],{"class":132},[126,390,162],{"class":233},[126,392,146],{"class":132},[126,394,149],{"class":132},[126,396,241],{"class":132},[126,398,399],{"class":244},"eligible",[126,401,146],{"class":132},[126,403,203],{"class":132},[126,405,407,409,412,414,416],{"class":128,"line":406},19,[126,408,230],{"class":132},[126,410,411],{"class":233},"edge_ttl",[126,413,146],{"class":132},[126,415,149],{"class":132},[126,417,152],{"class":132},[126,419,421,424,427,429,431,433,436,438],{"class":128,"line":420},20,[126,422,423],{"class":132},"            \"",[126,425,426],{"class":312},"mode",[126,428,146],{"class":132},[126,430,149],{"class":132},[126,432,241],{"class":132},[126,434,435],{"class":244},"custom",[126,437,146],{"class":132},[126,439,203],{"class":132},[126,441,443,445,448,450,452],{"class":128,"line":442},21,[126,444,423],{"class":132},[126,446,447],{"class":312},"seconds",[126,449,146],{"class":132},[126,451,149],{"class":132},[126,453,454],{"class":177}," 3600\n",[126,456,458],{"class":128,"line":457},22,[126,459,460],{"class":132},"          },\n",[126,462,464,466,469,471,473],{"class":128,"line":463},23,[126,465,230],{"class":132},[126,467,468],{"class":233},"browser_ttl",[126,470,146],{"class":132},[126,472,149],{"class":132},[126,474,152],{"class":132},[126,476,478,480,482,484,486,488,490,492],{"class":128,"line":477},24,[126,479,423],{"class":132},[126,481,426],{"class":312},[126,483,146],{"class":132},[126,485,149],{"class":132},[126,487,241],{"class":132},[126,489,435],{"class":244},[126,491,146],{"class":132},[126,493,203],{"class":132},[126,495,497,499,501,503,505],{"class":128,"line":496},25,[126,498,423],{"class":132},[126,500,447],{"class":312},[126,502,146],{"class":132},[126,504,149],{"class":132},[126,506,507],{"class":177}," 300\n",[126,509,511],{"class":128,"line":510},26,[126,512,460],{"class":132},[126,514,516,518,521,523,525],{"class":128,"line":515},27,[126,517,230],{"class":132},[126,519,520],{"class":233},"cache_key",[126,522,146],{"class":132},[126,524,149],{"class":132},[126,526,152],{"class":132},[126,528,530,532,534,536,538,540,543],{"class":128,"line":529},28,[126,531,423],{"class":132},[126,533,426],{"class":312},[126,535,146],{"class":132},[126,537,149],{"class":132},[126,539,241],{"class":132},[126,541,542],{"class":244},"default",[126,544,371],{"class":132},[126,546,548],{"class":128,"line":547},29,[126,549,460],{"class":132},[126,551,553,555,558,560,562,565,568,571,574,576,579],{"class":128,"line":552},30,[126,554,230],{"class":132},[126,556,557],{"class":233},"statuses",[126,559,146],{"class":132},[126,561,149],{"class":132},[126,563,564],{"class":132}," [",[126,566,567],{"class":177},"200",[126,569,570],{"class":132},",",[126,572,573],{"class":177}," 301",[126,575,570],{"class":132},[126,577,578],{"class":177}," 404",[126,580,581],{"class":132},"],\n",[126,583,585,587,590,592,594,597],{"class":128,"line":584},31,[126,586,230],{"class":132},[126,588,589],{"class":233},"stale_while_revalidate",[126,591,146],{"class":132},[126,593,149],{"class":132},[126,595,596],{"class":177}," 30",[126,598,203],{"class":132},[126,600,602,604,607,609,611],{"class":128,"line":601},32,[126,603,230],{"class":132},[126,605,606],{"class":233},"stale_if_error",[126,608,146],{"class":132},[126,610,149],{"class":132},[126,612,613],{"class":177}," 120\n",[126,615,617],{"class":128,"line":616},33,[126,618,619],{"class":132},"        }\n",[126,621,623],{"class":128,"line":622},34,[126,624,625],{"class":132},"      ]\n",[126,627,629],{"class":128,"line":628},35,[126,630,631],{"class":132},"    }\n",[126,633,635],{"class":128,"line":634},36,[126,636,637],{"class":132},"  }\n",[126,639,641],{"class":128,"line":640},37,[126,642,643],{"class":132},"}\n",[111,645,647],{"id":646},"rule-structure","Rule structure",[649,650,651,670],"table",{},[652,653,654],"thead",{},[655,656,657,661,664,667],"tr",{},[658,659,660],"th",{},"Field",[658,662,663],{},"Type",[658,665,666],{},"Required",[658,668,669],{},"Description",[671,672,673,689,702,721,735,758,772,785,798,814,832],"tbody",{},[655,674,675,680,683,686],{},[676,677,678],"td",{},[123,679,234],{},[676,681,682],{},"string",[676,684,685],{},"✅",[676,687,688],{},"Unique rule identifier",[655,690,691,695,697,699],{},[676,692,693],{},[123,694,257],{},[676,696,682],{},[676,698,685],{},[676,700,701],{},"Human-readable name",[655,703,704,708,711,714],{},[676,705,706],{},[123,707,178],{},[676,709,710],{},"bool",[676,712,713],{},"—",[676,715,716,717,720],{},"Enable\u002Fdisable rule (default: ",[123,718,719],{},"true",")",[655,722,723,727,730,732],{},[676,724,725],{},[123,726,291],{},[676,728,729],{},"array",[676,731,713],{},[676,733,734],{},"When to apply this rule (empty = always)",[655,736,737,741,744,746],{},[676,738,739],{},[123,740,162],{},[676,742,743],{},"enum",[676,745,713],{},[676,747,748,751,752,755,756,720],{},[123,749,750],{},"\"eligible\""," or ",[123,753,754],{},"\"bypass\""," (default: ",[123,757,750],{},[655,759,760,764,767,769],{},[676,761,762],{},[123,763,411],{},[676,765,766],{},"object",[676,768,685],{},[676,770,771],{},"How long to cache at the edge",[655,773,774,778,780,782],{},[676,775,776],{},[123,777,468],{},[676,779,766],{},[676,781,713],{},[676,783,784],{},"Browser cache TTL",[655,786,787,791,793,795],{},[676,788,789],{},[123,790,520],{},[676,792,766],{},[676,794,713],{},[676,796,797],{},"Custom cache key configuration",[655,799,800,804,806,808],{},[676,801,802],{},[123,803,557],{},[676,805,729],{},[676,807,713],{},[676,809,810,811,720],{},"HTTP status codes to cache (default: ",[123,812,813],{},"[200, 301, 404]",[655,815,816,820,823,825],{},[676,817,818],{},[123,819,589],{},[676,821,822],{},"number",[676,824,713],{},[676,826,827,828,831],{},"SWR window in seconds. Overrides origin ",[123,829,830],{},"Cache-Control"," header.",[655,833,834,838,840,842],{},[676,835,836],{},[123,837,606],{},[676,839,822],{},[676,841,713],{},[676,843,844,845,831],{},"SIE window in seconds. Overrides origin ",[123,846,830],{},[111,848,850],{"id":849},"cache-modes","Cache modes",[852,853,854],"h3",{"id":399},"Eligible",[102,856,857],{},"The response is eligible for caching. The plugin checks:",[859,860,861,868,873,880],"ol",{},[862,863,864,865,867],"li",{},"Response status is in the ",[123,866,557],{}," list",[862,869,870,871],{},"Response body is within ",[123,872,193],{},[862,874,875,876,879],{},"No ",[123,877,878],{},"Set-Cookie"," header",[862,881,875,882,885,886,889,890],{},[123,883,884],{},"Cache-Control: private",", ",[123,887,888],{},"no-store",", or ",[123,891,892],{},"no-cache",[852,894,896],{"id":895},"bypass","Bypass",[102,898,899],{},"Skip the cache entirely for matching requests.",[116,901,903],{"className":118,"code":902,"language":120,"meta":121,"style":121},"{\n  \"conditions\": [\n    { \"left\": \"req.path\", \"operator\": \"starts_with\", \"value\": \"\u002Fapi\u002F\" }\n  ],\n  \"cache\": \"bypass\"\n}\n",[123,904,905,909,921,977,982,998],{"__ignoreMap":121},[126,906,907],{"class":128,"line":129},[126,908,133],{"class":132},[126,910,911,913,915,917,919],{"class":128,"line":136},[126,912,139],{"class":132},[126,914,291],{"class":142},[126,916,146],{"class":132},[126,918,149],{"class":132},[126,920,218],{"class":132},[126,922,923,926,928,930,932,934,936,938,940,942,944,946,948,950,952,955,957,959,961,963,965,967,969,972,974],{"class":128,"line":155},[126,924,925],{"class":132},"    {",[126,927,241],{"class":132},[126,929,313],{"class":161},[126,931,146],{"class":132},[126,933,149],{"class":132},[126,935,241],{"class":132},[126,937,322],{"class":244},[126,939,146],{"class":132},[126,941,570],{"class":132},[126,943,241],{"class":132},[126,945,334],{"class":161},[126,947,146],{"class":132},[126,949,149],{"class":132},[126,951,241],{"class":132},[126,953,954],{"class":244},"starts_with",[126,956,146],{"class":132},[126,958,570],{"class":132},[126,960,241],{"class":132},[126,962,355],{"class":161},[126,964,146],{"class":132},[126,966,149],{"class":132},[126,968,241],{"class":132},[126,970,971],{"class":244},"\u002Fapi\u002F",[126,973,146],{"class":132},[126,975,976],{"class":132}," }\n",[126,978,979],{"class":128,"line":171},[126,980,981],{"class":132},"  ],\n",[126,983,984,986,988,990,992,994,996],{"class":128,"line":188},[126,985,139],{"class":132},[126,987,162],{"class":142},[126,989,146],{"class":132},[126,991,149],{"class":132},[126,993,241],{"class":132},[126,995,895],{"class":244},[126,997,371],{"class":132},[126,999,1000],{"class":128,"line":206},[126,1001,643],{"class":132},[111,1003,1005],{"id":1004},"edge-ttl","Edge TTL",[102,1007,1008],{},"Controls how long the gateway caches the response.",[852,1010,1012],{"id":1011},"origin-mode","Origin mode",[102,1014,1015,1016,751,1018,1021],{},"Use the upstream's ",[123,1017,830],{},[123,1019,1020],{},"Expires"," header:",[116,1023,1025],{"className":118,"code":1024,"language":120,"meta":121,"style":121},"{\n  \"edge_ttl\": {\n    \"mode\": \"origin\"\n  }\n}\n",[123,1026,1027,1031,1043,1060,1064],{"__ignoreMap":121},[126,1028,1029],{"class":128,"line":129},[126,1030,133],{"class":132},[126,1032,1033,1035,1037,1039,1041],{"class":128,"line":136},[126,1034,139],{"class":132},[126,1036,411],{"class":142},[126,1038,146],{"class":132},[126,1040,149],{"class":132},[126,1042,152],{"class":132},[126,1044,1045,1047,1049,1051,1053,1055,1058],{"class":128,"line":155},[126,1046,158],{"class":132},[126,1048,426],{"class":161},[126,1050,146],{"class":132},[126,1052,149],{"class":132},[126,1054,241],{"class":132},[126,1056,1057],{"class":244},"origin",[126,1059,371],{"class":132},[126,1061,1062],{"class":128,"line":171},[126,1063,637],{"class":132},[126,1065,1066],{"class":128,"line":188},[126,1067,643],{"class":132},[102,1069,1070,1071,1073,1074,1077,1078,1081,1082,1084],{},"When mode is ",[123,1072,1057],{},", the gateway reads ",[123,1075,1076],{},"s-maxage"," first, then ",[123,1079,1080],{},"max-age"," from the upstream ",[123,1083,830],{}," header. If neither is present, the response is not cached.",[852,1086,1088],{"id":1087},"custom-mode","Custom mode",[102,1090,1091],{},"Override with a fixed TTL:",[116,1093,1095],{"className":118,"code":1094,"language":120,"meta":121,"style":121},"{\n  \"edge_ttl\": {\n    \"mode\": \"custom\",\n    \"seconds\": 3600\n  }\n}\n",[123,1096,1097,1101,1113,1131,1143,1147],{"__ignoreMap":121},[126,1098,1099],{"class":128,"line":129},[126,1100,133],{"class":132},[126,1102,1103,1105,1107,1109,1111],{"class":128,"line":136},[126,1104,139],{"class":132},[126,1106,411],{"class":142},[126,1108,146],{"class":132},[126,1110,149],{"class":132},[126,1112,152],{"class":132},[126,1114,1115,1117,1119,1121,1123,1125,1127,1129],{"class":128,"line":155},[126,1116,158],{"class":132},[126,1118,426],{"class":161},[126,1120,146],{"class":132},[126,1122,149],{"class":132},[126,1124,241],{"class":132},[126,1126,435],{"class":244},[126,1128,146],{"class":132},[126,1130,203],{"class":132},[126,1132,1133,1135,1137,1139,1141],{"class":128,"line":171},[126,1134,158],{"class":132},[126,1136,447],{"class":161},[126,1138,146],{"class":132},[126,1140,149],{"class":132},[126,1142,454],{"class":177},[126,1144,1145],{"class":128,"line":188},[126,1146,637],{"class":132},[126,1148,1149],{"class":128,"line":206},[126,1150,643],{"class":132},[111,1152,1154],{"id":1153},"stale-while-revalidate-and-stale-if-error","Stale-while-revalidate and stale-if-error",[102,1156,1157,1158,1161,1162,1165],{},"The gateway supports ",[123,1159,1160],{},"stale-while-revalidate"," and ",[123,1163,1164],{},"stale-if-error"," directives. These can be configured in two ways:",[852,1167,1169],{"id":1168},"_1-gateway-level-configuration-recommended","1. Gateway-level configuration (recommended)",[102,1171,1172,1173,1175],{},"Set SWR\u002FSIE directly in the cache rule. This overrides any origin ",[123,1174,830],{}," header values:",[116,1177,1179],{"className":118,"code":1178,"language":120,"meta":121,"style":121},"{\n  \"id\": \"cache-api\",\n  \"name\": \"Cache API\",\n  \"cache\": \"eligible\",\n  \"edge_ttl\": { \"mode\": \"origin\" },\n  \"stale_while_revalidate\": 30,\n  \"stale_if_error\": 120,\n  \"statuses\": [200]\n}\n",[123,1180,1181,1185,1204,1223,1241,1271,1285,1300,1317],{"__ignoreMap":121},[126,1182,1183],{"class":128,"line":129},[126,1184,133],{"class":132},[126,1186,1187,1189,1191,1193,1195,1197,1200,1202],{"class":128,"line":136},[126,1188,139],{"class":132},[126,1190,234],{"class":142},[126,1192,146],{"class":132},[126,1194,149],{"class":132},[126,1196,241],{"class":132},[126,1198,1199],{"class":244},"cache-api",[126,1201,146],{"class":132},[126,1203,203],{"class":132},[126,1205,1206,1208,1210,1212,1214,1216,1219,1221],{"class":128,"line":155},[126,1207,139],{"class":132},[126,1209,257],{"class":142},[126,1211,146],{"class":132},[126,1213,149],{"class":132},[126,1215,241],{"class":132},[126,1217,1218],{"class":244},"Cache API",[126,1220,146],{"class":132},[126,1222,203],{"class":132},[126,1224,1225,1227,1229,1231,1233,1235,1237,1239],{"class":128,"line":171},[126,1226,139],{"class":132},[126,1228,162],{"class":142},[126,1230,146],{"class":132},[126,1232,149],{"class":132},[126,1234,241],{"class":132},[126,1236,399],{"class":244},[126,1238,146],{"class":132},[126,1240,203],{"class":132},[126,1242,1243,1245,1247,1249,1251,1254,1256,1258,1260,1262,1264,1266,1268],{"class":128,"line":188},[126,1244,139],{"class":132},[126,1246,411],{"class":142},[126,1248,146],{"class":132},[126,1250,149],{"class":132},[126,1252,1253],{"class":132}," {",[126,1255,241],{"class":132},[126,1257,426],{"class":161},[126,1259,146],{"class":132},[126,1261,149],{"class":132},[126,1263,241],{"class":132},[126,1265,1057],{"class":244},[126,1267,146],{"class":132},[126,1269,1270],{"class":132}," },\n",[126,1272,1273,1275,1277,1279,1281,1283],{"class":128,"line":206},[126,1274,139],{"class":132},[126,1276,589],{"class":142},[126,1278,146],{"class":132},[126,1280,149],{"class":132},[126,1282,596],{"class":177},[126,1284,203],{"class":132},[126,1286,1287,1289,1291,1293,1295,1298],{"class":128,"line":221},[126,1288,139],{"class":132},[126,1290,606],{"class":142},[126,1292,146],{"class":132},[126,1294,149],{"class":132},[126,1296,1297],{"class":177}," 120",[126,1299,203],{"class":132},[126,1301,1302,1304,1306,1308,1310,1312,1314],{"class":128,"line":227},[126,1303,139],{"class":132},[126,1305,557],{"class":142},[126,1307,146],{"class":132},[126,1309,149],{"class":132},[126,1311,564],{"class":132},[126,1313,567],{"class":177},[126,1315,1316],{"class":132},"]\n",[126,1318,1319],{"class":128,"line":252},[126,1320,643],{"class":132},[852,1322,1324],{"id":1323},"_2-origin-level-automatic","2. Origin-level (automatic)",[102,1326,1327,1328,1021],{},"If not configured in the gateway, SWR\u002FSIE are parsed from the upstream ",[123,1329,830],{},[116,1331,1336],{"className":1332,"code":1334,"language":1335},[1333],"language-text","Cache-Control: s-maxage=60, stale-while-revalidate=30, stale-if-error=60\n","text",[123,1337,1334],{"__ignoreMap":121},[852,1339,1341],{"id":1340},"priority","Priority",[649,1343,1344,1353],{},[652,1345,1346],{},[655,1347,1348,1351],{},[658,1349,1350],{},"Source",[658,1352,1341],{},[671,1354,1355,1368,1379],{},[655,1356,1357,1362],{},[676,1358,1359,1360],{},"Gateway config ",[123,1361,589],{},[676,1363,1364,1367],{},[106,1365,1366],{},"Highest"," — overrides origin header",[655,1369,1370,1376],{},[676,1371,1372,1373],{},"Origin ",[123,1374,1375],{},"Cache-Control: stale-while-revalidate",[676,1377,1378],{},"Used if no gateway config",[655,1380,1381,1384],{},[676,1382,1383],{},"Neither",[676,1385,1386],{},"SWR = 0 (no revalidation window)",[102,1388,1389,1390,1392],{},"Same priority applies to ",[123,1391,606],{},".",[852,1394,1396],{"id":1395},"how-theyre-parsed","How they're parsed",[102,1398,1399],{},"When the gateway stores a cached response, it calculates TTLs:",[649,1401,1402,1414],{},[652,1403,1404],{},[655,1405,1406,1409,1411],{},[658,1407,1408],{},"Directive",[658,1410,1350],{},[658,1412,1413],{},"Stored in cache entry",[671,1415,1416,1433,1448,1461],{},[655,1417,1418,1422,1425],{},[676,1419,1420],{},[123,1421,1076],{},[676,1423,1424],{},"Origin header",[676,1426,1427,1429,1430,720],{},[123,1428,411],{}," (if ",[123,1431,1432],{},"mode: origin",[655,1434,1435,1439,1441],{},[676,1436,1437],{},[123,1438,1080],{},[676,1440,1424],{},[676,1442,1443,1445,1446,720],{},[123,1444,411],{}," fallback (if ",[123,1447,1432],{},[655,1449,1450,1454,1457],{},[676,1451,1452],{},[123,1453,1160],{},[676,1455,1456],{},"Gateway config OR origin header",[676,1458,1459],{},[123,1460,589],{},[655,1462,1463,1467,1469],{},[676,1464,1465],{},[123,1466,1164],{},[676,1468,1456],{},[676,1470,1471],{},[123,1472,606],{},[852,1474,1476],{"id":1475},"timeline","Timeline",[116,1478,1481],{"className":1479,"code":1480,"language":1335},[1333],"edge_ttl = 60s, stale_while_revalidate = 30s, stale_if_error = 60s\n\nmax_stale = max(SWR, SIE) = max(30, 60) = 60s\nfully_expired = edge_ttl + max_stale = 60 + 60 = 120s\n\n├── 0s ────── 60s ──────────────── 120s ──────────────────────┤\n│                │                        │                   │\n│   FRESH        │   STALE                │  CACHE MISS       │\n│   (HIT)        │   (serve stale +       │  (entry treated   │\n│                │    revalidate via       │   as expired)     │\n│                │    singleflight)        │                   │\n│                │                        │                   │\n│                ▼                        ▼                   │\n│           edge_ttl              edge_ttl + max(SWR, SIE)    │\n│            = 60s                      = 120s                │\n│                                                             │\n│  Note: entry is not physically removed from store,          │\n│  but lookup() returns Miss (treated as cache miss)          │\n",[123,1482,1480],{"__ignoreMap":121},[852,1484,1486],{"id":1485},"cache-states","Cache states",[649,1488,1489,1502],{},[652,1490,1491],{},[655,1492,1493,1496,1499],{},[658,1494,1495],{},"State",[658,1497,1498],{},"Age range",[658,1500,1501],{},"Behavior",[671,1503,1504,1519,1534],{},[655,1505,1506,1511,1516],{},[676,1507,1508],{},[106,1509,1510],{},"Fresh",[676,1512,1513],{},[123,1514,1515],{},"age \u003C edge_ttl",[676,1517,1518],{},"Cache HIT — serve immediately",[655,1520,1521,1526,1531],{},[676,1522,1523],{},[106,1524,1525],{},"Stale (SWR window)",[676,1527,1528],{},[123,1529,1530],{},"edge_ttl ≤ age \u003C edge_ttl + max(SWR, SIE)",[676,1532,1533],{},"Serve stale + revalidate",[655,1535,1536,1541,1546],{},[676,1537,1538],{},[106,1539,1540],{},"Fully expired",[676,1542,1543],{},[123,1544,1545],{},"age ≥ edge_ttl + max(SWR, SIE)",[676,1547,1548],{},"Cache MISS — entry removed",[1550,1551,1552,1554,1555,1558],"note",{},[123,1553,606],{}," extends the total stale serving window (used in ",[123,1556,1557],{},"max(SWR, SIE)"," calculation). Within this window, stale data can be served. Error-specific gating (only serving stale when the upstream returns 5xx\u002Ftimeout) is a planned enhancement — currently the time window alone determines eligibility.",[111,1560,1562],{"id":1561},"singleflight-revalidation","Singleflight revalidation",[102,1564,1565,1566,1569],{},"When a cache entry becomes stale, the gateway uses ",[106,1567,1568],{},"per-key locking"," to ensure only one request refreshes the cache. Concurrent requests serve stale data while waiting.",[852,1571,1573],{"id":1572},"how-it-works","How it works",[116,1575,1578],{"className":1576,"code":1577,"language":1335},[1333],"                    ┌──────────────┐\n                    │  Cache Lookup │\n                    └──────┬───────┘\n                           │\n             ┌─────────────┼──────────────┐\n             │             │              │\n          Fresh       Stale+lock      Stale+no lock\n             │             │              │\n          [HIT]        [HIT\u002FSTALE]    try_lock_owned()\n        serve cached   serve stale    ┌────┴────┐\n        status=HIT     status=        │         │\n                       REVALIDATING  Ok(guard)  Err\n                                      │         │\n                           status=    serve stale\n                           REVALIDATING  status=Stale\n                           cache_should_store=true\n                           return Continue\n                           (go to origin normally)\n                                      │\n                           origin responds →\n                           response_body_filter stores fresh data →\n                           ctx.revalidation_guard = None (lock releases) →\n                           revalidating.remove(key) →\n                           next request sees fresh data → cache HIT\n",[123,1579,1577],{"__ignoreMap":121},[852,1581,1583],{"id":1582},"request-flow","Request flow",[1585,1586,1588],"h4",{"id":1587},"request-1-stale-no-lock-first-request","Request 1 — Stale + no lock (first request)",[116,1590,1593],{"className":1591,"code":1592,"language":1335},[1333],"t=61s: Request arrives → cache entry is stale (age > edge_ttl)\n       → No lock held for this key\n       → Acquire lock (try_lock_owned)\n       → Set status = REVALIDATING\n       → Set cache_should_store = true\n       → Return Continue (go to origin like a normal cache miss)\n       → Origin responds with fresh data\n       → response_body_filter stores in cache\n       → Lock released (RevalidationGuard drops)\n",[123,1594,1592],{"__ignoreMap":121},[102,1596,1597,1600,1601,1604],{},[106,1598,1599],{},"Response:"," ",[123,1602,1603],{},"Quayel-Cache-Status: REVALIDATING"," — response comes from origin.",[1585,1606,1608],{"id":1607},"request-2-stale-lock-held-concurrent-request","Request 2 — Stale + lock held (concurrent request)",[116,1610,1613],{"className":1611,"code":1612,"language":1335},[1333],"t=62s: Request arrives → cache entry is stale\n       → Lock is held (someone else is refreshing)\n       → Serve stale cached data\n       → Set status = REVALIDATING\n",[123,1614,1612],{"__ignoreMap":121},[102,1616,1617,1600,1619,1621],{},[106,1618,1599],{},[123,1620,1603],{}," — response comes from stale cache.",[1585,1623,1625],{"id":1624},"request-3-after-revalidation-completes","Request 3 — After revalidation completes",[116,1627,1630],{"className":1628,"code":1629,"language":1335},[1333],"t=63s: Request arrives → cache entry is fresh (just refreshed)\n       → Serve cached data\n       → Set status = HIT\n",[123,1631,1629],{"__ignoreMap":121},[102,1633,1634,1600,1636,1639],{},[106,1635,1599],{},[123,1637,1638],{},"Quayel-Cache-Status: HIT"," — response comes from fresh cache.",[852,1641,1643],{"id":1642},"why-this-is-correct","Why this is correct",[649,1645,1646,1655],{},[652,1647,1648],{},[655,1649,1650,1653],{},[658,1651,1652],{},"Property",[658,1654,669],{},[671,1656,1657,1671,1681,1691,1713],{},[655,1658,1659,1664],{},[676,1660,1661],{},[106,1662,1663],{},"Lock is the mechanism",[676,1665,1666,1667,1670],{},"Not a time window. Even with ",[123,1668,1669],{},"stale-while-revalidate=0",", concurrent requests serve stale while someone refreshes.",[655,1672,1673,1678],{},[676,1674,1675],{},[106,1676,1677],{},"No background tasks",[676,1679,1680],{},"The first request IS the refresh. It goes to origin like a normal cache miss, gets fresh data, stores it.",[655,1682,1683,1688],{},[676,1684,1685],{},[106,1686,1687],{},"No separate HTTP client",[676,1689,1690],{},"Uses the normal proxy flow. Headers, middleware, TLS — everything works.",[655,1692,1693,1698],{},[676,1694,1695],{},[106,1696,1697],{},"Lock auto-releases",[676,1699,1700,1701,1704,1705,1708,1709,1712],{},"The ",[123,1702,1703],{},"RevalidationGuard"," is stored in ",[123,1706,1707],{},"RequestContext",". When the request completes, ",[123,1710,1711],{},"ctx"," drops → guard drops → lock releases.",[655,1714,1715,1720],{},[676,1716,1717],{},[106,1718,1719],{},"No stampedes",[676,1721,1722],{},"Only one request per key goes to origin. All others serve stale.",[852,1724,1726],{"id":1725},"race-condition-handling","Race condition handling",[102,1728,1729,1730,1733,1734,1161,1737,149],{},"There's a small window between ",[123,1731,1732],{},"lookup()"," returning ",[123,1735,1736],{},"Stale",[123,1738,1739],{},"try_lock_owned()",[116,1741,1744],{"className":1742,"code":1743,"language":1335},[1333],"Thread A: lookup() → Stale\nThread B: lookup() → Stale  (concurrent)\nThread A: try_lock_owned() → Ok  → go to origin\nThread B: try_lock_owned() → Err → serve stale (status=Stale)\n",[123,1745,1743],{"__ignoreMap":121},[102,1747,1748],{},"This is safe — Thread B falls back to serving stale data.",[111,1750,1752],{"id":1751},"stale-if-error-sie","Stale-if-error (SIE)",[102,1754,1700,1755,1757],{},[123,1756,1164],{}," directive extends the cache lifetime for error scenarios. When the upstream returns an error (5xx, timeout, connection failure), the gateway can serve stale data instead.",[852,1759,1761],{"id":1760},"timeline-with-sie","Timeline with SIE",[116,1763,1766],{"className":1764,"code":1765,"language":1335},[1333],"edge_ttl = 60s, stale_while_revalidate = 0s, stale_if_error = 120s\n\n├── 0s ────── 60s ────────────── 180s ──┤\n│                │                      │\n│   FRESH        │   STALE (SIE)       │  FULLY EXPIRED\n│   (HIT)        │                      │  (MISS)\n│                │                      │\n│                ▼                      ▼\n│            edge_ttl            edge_ttl + SIE\n│             + 0s                + 120s = 180s\n",[123,1767,1765],{"__ignoreMap":121},[852,1769,1771],{"id":1770},"how-sie-works","How SIE works",[859,1773,1774,1782,1790,1793],{},[862,1775,1776,1777,1779,1780,879],{},"Cache entry is stored with ",[123,1778,606],{}," duration from origin's ",[123,1781,830],{},[862,1783,1784,1786,1787],{},[123,1785,606],{}," extends the total stale window: ",[123,1788,1789],{},"fully_expired = edge_ttl + max(SWR, SIE)",[862,1791,1792],{},"Within this extended window, stale entries are eligible for serving via the singleflight revalidation mechanism",[862,1794,1795],{},"When the first request fetches fresh data from origin and stores it, subsequent requests get fresh cache hits",[852,1797,1799],{"id":1798},"planned-enhancement-error-specific-gating","Planned enhancement: error-specific gating",[102,1801,1802,1803,1805],{},"In a future version, ",[123,1804,606],{}," will only activate when the upstream actually returns an error:",[1807,1808,1809,1816],"ul",{},[862,1810,1811,1812,1815],{},"If origin returns ",[106,1813,1814],{},"success (2xx\u002F3xx\u002F4xx)",": cache is updated with fresh data",[862,1817,1811,1818,1821],{},[106,1819,1820],{},"error (5xx, timeout, connection failure)",": gateway serves stale cached data instead of the error",[852,1823,1825],{"id":1824},"configuration-example","Configuration example",[102,1827,1828],{},"Origin sets the directive:",[116,1830,1834],{"className":1831,"code":1832,"language":1833,"meta":121,"style":121},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","HTTP\u002F1.1 200 OK\nCache-Control: s-maxage=60, stale-while-revalidate=10, stale-if-error=120\n","http",[123,1835,1836,1841],{"__ignoreMap":121},[126,1837,1838],{"class":128,"line":129},[126,1839,1840],{},"HTTP\u002F1.1 200 OK\n",[126,1842,1843],{"class":128,"line":136},[126,1844,1845],{},"Cache-Control: s-maxage=60, stale-while-revalidate=10, stale-if-error=120\n",[102,1847,1848],{},"The gateway automatically reads and stores these values. No gateway-side configuration needed.",[111,1850,1852],{"id":1851},"browser-ttl","Browser TTL",[102,1854,1855,1856,1858],{},"Controls the ",[123,1857,830],{}," header sent to the client.",[852,1860,1862],{"id":1861},"bypass-mode","Bypass mode",[102,1864,1865],{},"Don't modify browser caching:",[116,1867,1869],{"className":118,"code":1868,"language":120,"meta":121,"style":121},"{\n  \"browser_ttl\": {\n    \"mode\": \"bypass\"\n  }\n}\n",[123,1870,1871,1875,1887,1903,1907],{"__ignoreMap":121},[126,1872,1873],{"class":128,"line":129},[126,1874,133],{"class":132},[126,1876,1877,1879,1881,1883,1885],{"class":128,"line":136},[126,1878,139],{"class":132},[126,1880,468],{"class":142},[126,1882,146],{"class":132},[126,1884,149],{"class":132},[126,1886,152],{"class":132},[126,1888,1889,1891,1893,1895,1897,1899,1901],{"class":128,"line":155},[126,1890,158],{"class":132},[126,1892,426],{"class":161},[126,1894,146],{"class":132},[126,1896,149],{"class":132},[126,1898,241],{"class":132},[126,1900,895],{"class":244},[126,1902,371],{"class":132},[126,1904,1905],{"class":128,"line":171},[126,1906,637],{"class":132},[126,1908,1909],{"class":128,"line":188},[126,1910,643],{"class":132},[852,1912,1012],{"id":1913},"origin-mode-1",[102,1915,1015,1916,1021],{},[123,1917,830],{},[116,1919,1921],{"className":118,"code":1920,"language":120,"meta":121,"style":121},"{\n  \"browser_ttl\": {\n    \"mode\": \"origin\"\n  }\n}\n",[123,1922,1923,1927,1939,1955,1959],{"__ignoreMap":121},[126,1924,1925],{"class":128,"line":129},[126,1926,133],{"class":132},[126,1928,1929,1931,1933,1935,1937],{"class":128,"line":136},[126,1930,139],{"class":132},[126,1932,468],{"class":142},[126,1934,146],{"class":132},[126,1936,149],{"class":132},[126,1938,152],{"class":132},[126,1940,1941,1943,1945,1947,1949,1951,1953],{"class":128,"line":155},[126,1942,158],{"class":132},[126,1944,426],{"class":161},[126,1946,146],{"class":132},[126,1948,149],{"class":132},[126,1950,241],{"class":132},[126,1952,1057],{"class":244},[126,1954,371],{"class":132},[126,1956,1957],{"class":128,"line":171},[126,1958,637],{"class":132},[126,1960,1961],{"class":128,"line":188},[126,1962,643],{"class":132},[852,1964,1088],{"id":1965},"custom-mode-1",[102,1967,1968],{},"Set a specific browser TTL:",[116,1970,1972],{"className":118,"code":1971,"language":120,"meta":121,"style":121},"{\n  \"browser_ttl\": {\n    \"mode\": \"custom\",\n    \"seconds\": 300\n  }\n}\n",[123,1973,1974,1978,1990,2008,2020,2024],{"__ignoreMap":121},[126,1975,1976],{"class":128,"line":129},[126,1977,133],{"class":132},[126,1979,1980,1982,1984,1986,1988],{"class":128,"line":136},[126,1981,139],{"class":132},[126,1983,468],{"class":142},[126,1985,146],{"class":132},[126,1987,149],{"class":132},[126,1989,152],{"class":132},[126,1991,1992,1994,1996,1998,2000,2002,2004,2006],{"class":128,"line":155},[126,1993,158],{"class":132},[126,1995,426],{"class":161},[126,1997,146],{"class":132},[126,1999,149],{"class":132},[126,2001,241],{"class":132},[126,2003,435],{"class":244},[126,2005,146],{"class":132},[126,2007,203],{"class":132},[126,2009,2010,2012,2014,2016,2018],{"class":128,"line":171},[126,2011,158],{"class":132},[126,2013,447],{"class":161},[126,2015,146],{"class":132},[126,2017,149],{"class":132},[126,2019,507],{"class":177},[126,2021,2022],{"class":128,"line":188},[126,2023,637],{"class":132},[126,2025,2026],{"class":128,"line":206},[126,2027,643],{"class":132},[111,2029,2031],{"id":2030},"cache-keys","Cache keys",[852,2033,2035],{"id":2034},"default-mode","Default mode",[102,2037,2038,2039],{},"The default cache key is: ",[123,2040,2041],{},"scheme|host|path",[116,2043,2045],{"className":118,"code":2044,"language":120,"meta":121,"style":121},"{\n  \"cache_key\": {\n    \"mode\": \"default\"\n  }\n}\n",[123,2046,2047,2051,2063,2079,2083],{"__ignoreMap":121},[126,2048,2049],{"class":128,"line":129},[126,2050,133],{"class":132},[126,2052,2053,2055,2057,2059,2061],{"class":128,"line":136},[126,2054,139],{"class":132},[126,2056,520],{"class":142},[126,2058,146],{"class":132},[126,2060,149],{"class":132},[126,2062,152],{"class":132},[126,2064,2065,2067,2069,2071,2073,2075,2077],{"class":128,"line":155},[126,2066,158],{"class":132},[126,2068,426],{"class":161},[126,2070,146],{"class":132},[126,2072,149],{"class":132},[126,2074,241],{"class":132},[126,2076,542],{"class":244},[126,2078,371],{"class":132},[126,2080,2081],{"class":128,"line":171},[126,2082,637],{"class":132},[126,2084,2085],{"class":128,"line":188},[126,2086,643],{"class":132},[852,2088,1088],{"id":2089},"custom-mode-2",[102,2091,2092],{},"Add additional components to the cache key:",[116,2094,2096],{"className":118,"code":2095,"language":120,"meta":121,"style":121},"{\n  \"cache_key\": {\n    \"mode\": \"custom\",\n    \"parts\": [\n      \"ip.country\",\n      \"req.header.Accept-Language\"\n    ]\n  }\n}\n",[123,2097,2098,2102,2114,2132,2145,2156,2165,2170,2174],{"__ignoreMap":121},[126,2099,2100],{"class":128,"line":129},[126,2101,133],{"class":132},[126,2103,2104,2106,2108,2110,2112],{"class":128,"line":136},[126,2105,139],{"class":132},[126,2107,520],{"class":142},[126,2109,146],{"class":132},[126,2111,149],{"class":132},[126,2113,152],{"class":132},[126,2115,2116,2118,2120,2122,2124,2126,2128,2130],{"class":128,"line":155},[126,2117,158],{"class":132},[126,2119,426],{"class":161},[126,2121,146],{"class":132},[126,2123,149],{"class":132},[126,2125,241],{"class":132},[126,2127,435],{"class":244},[126,2129,146],{"class":132},[126,2131,203],{"class":132},[126,2133,2134,2136,2139,2141,2143],{"class":128,"line":171},[126,2135,158],{"class":132},[126,2137,2138],{"class":161},"parts",[126,2140,146],{"class":132},[126,2142,149],{"class":132},[126,2144,218],{"class":132},[126,2146,2147,2149,2152,2154],{"class":128,"line":188},[126,2148,174],{"class":132},[126,2150,2151],{"class":244},"ip.country",[126,2153,146],{"class":132},[126,2155,203],{"class":132},[126,2157,2158,2160,2163],{"class":128,"line":206},[126,2159,174],{"class":132},[126,2161,2162],{"class":244},"req.header.Accept-Language",[126,2164,371],{"class":132},[126,2166,2167],{"class":128,"line":221},[126,2168,2169],{"class":132},"    ]\n",[126,2171,2172],{"class":128,"line":227},[126,2173,637],{"class":132},[126,2175,2176],{"class":128,"line":252},[126,2177,643],{"class":132},[102,2179,2180,2181],{},"This creates a cache key like: ",[123,2182,2183],{},"https|example.com|\u002Fpage|US|en-US",[852,2185,2187],{"id":2186},"available-cache-key-parts","Available cache key parts",[102,2189,2190,2191,2196],{},"Any ",[2192,2193,2195],"a",{"href":2194},"\u002Fquayel-gateway\u002Fconditions#condition-paths","condition path"," can be used as a cache key part:",[649,2198,2199,2208],{},[652,2200,2201],{},[655,2202,2203,2206],{},[658,2204,2205],{},"Part",[658,2207,669],{},[671,2209,2210,2219,2229,2239,2249],{},[655,2211,2212,2216],{},[676,2213,2214],{},[123,2215,2151],{},[676,2217,2218],{},"Cache by country",[655,2220,2221,2226],{},[676,2222,2223],{},[123,2224,2225],{},"ip.asn",[676,2227,2228],{},"Cache by ASN",[655,2230,2231,2236],{},[676,2232,2233],{},[123,2234,2235],{},"req.header.\u003Cname>",[676,2237,2238],{},"Cache by header value",[655,2240,2241,2246],{},[676,2242,2243],{},[123,2244,2245],{},"req.query.\u003Cname>",[676,2247,2248],{},"Cache by query parameter",[655,2250,2251,2256],{},[676,2252,2253],{},[123,2254,2255],{},"req.cookie.\u003Cname>",[676,2257,2258],{},"Cache by cookie value",[111,2260,1573],{"id":2261},"how-it-works-1",[116,2263,2266],{"className":2264,"code":2265,"language":1335},[1333],"Request arrives\n    │\n    ▼\n1. Evaluate conditions → find matching rule\n    │\n    ├── No match → skip cache\n    │\n    └── Match:\n        │\n        ├── cache = \"bypass\" → skip cache\n        │\n        └── cache = \"eligible\":\n            │\n            ├── 2. Generate cache key (scheme|host|path + custom parts)\n            ├── 3. Hash cache key (FxHash → 16-char hex)\n            │\n            ├── 4. Lookup in DashMap\n            │   │\n            │   ├── FRESH (age \u003C edge_ttl)\n            │   │   → CacheLookup::Hit → serve cached response\n            │   │   → Quayel-Cache-Status: HIT\n            │   │   → Pipeline short-circuits (no upstream)\n            │   │\n            │   ├── STALE + lock held (someone else revalidating)\n            │   │   → CacheLookup::HitRevalidating → serve stale response\n            │   │   → Quayel-Cache-Status: REVALIDATING\n            │   │\n            │   ├── STALE + no lock\n            │   │   → try_lock_owned()\n            │   │   ├── Ok(guard) → become the refresh request\n            │   │   │   → Quayel-Cache-Status: REVALIDATING\n            │   │   │   → Continue to origin (normal proxy flow)\n            │   │   │   → Origin responds → store in cache → lock releases\n            │   │   │\n            │   │   └── Err (race condition)\n            │   │       → Serve stale response\n            │   │       → Quayel-Cache-Status: STALE\n            │   │\n            │   ├── FULLY EXPIRED (age ≥ edge_ttl + max(SWR, SIE))\n            │   │   → CacheLookup::Miss → entry removed\n            │   │   → Continue to origin\n            │   │\n            │   └── MISS (no entry)\n            │       → CacheLookup::Miss → Continue to origin\n            │\n            └── 5. After origin responds (response_body_filter):\n                │\n                ├── Parse Cache-Control headers\n                │   → Extract s-maxage, max-age, stale-while-revalidate, stale-if-error\n                │\n                ├── Check cacheability\n                │   ├── Status in statuses list?\n                │   ├── Body \u003C max_object_size?\n                │   ├── No Set-Cookie?\n                │   └── No no-cache\u002Fno-store\u002Fprivate?\n                │\n                ├── Calculate TTLs\n                │   → edge_ttl (from mode + headers)\n                │   → stale_while_revalidate (from Cache-Control)\n                │   → stale_if_error (from Cache-Control)\n                │\n                ├── Store in cache\n                │   → DashMap::insert(key, CacheEntry)\n                │\n                └── Release revalidation lock (if held)\n                    → ctx.revalidation_guard = None\n                    → revalidating.remove(key)\n",[123,2267,2265],{"__ignoreMap":121},[111,2269,2271],{"id":2270},"cache-status-values","Cache status values",[649,2273,2274,2287],{},[652,2275,2276],{},[655,2277,2278,2281,2284],{},[658,2279,2280],{},"Status",[658,2282,2283],{},"Header Value",[658,2285,2286],{},"Meaning",[671,2288,2289,2304,2319,2334,2349,2363,2377,2391],{},[655,2290,2291,2296,2301],{},[676,2292,2293],{},[106,2294,2295],{},"None",[676,2297,2298],{},[123,2299,2300],{},"NONE",[676,2302,2303],{},"No cache rule matched",[655,2305,2306,2311,2316],{},[676,2307,2308],{},[106,2309,2310],{},"Hit",[676,2312,2313],{},[123,2314,2315],{},"HIT",[676,2317,2318],{},"Response served from fresh cache",[655,2320,2321,2326,2331],{},[676,2322,2323],{},[106,2324,2325],{},"Miss",[676,2327,2328],{},[123,2329,2330],{},"MISS",[676,2332,2333],{},"Cache miss, fetched from upstream",[655,2335,2336,2341,2346],{},[676,2337,2338],{},[106,2339,2340],{},"Expired",[676,2342,2343],{},[123,2344,2345],{},"EXPIRED",[676,2347,2348],{},"(Reserved for future use)",[655,2350,2351,2355,2360],{},[676,2352,2353],{},[106,2354,896],{},[676,2356,2357],{},[123,2358,2359],{},"BYPASS",[676,2361,2362],{},"Cache bypassed by rule",[655,2364,2365,2370,2375],{},[676,2366,2367],{},[106,2368,2369],{},"Dynamic",[676,2371,2372],{},[123,2373,2374],{},"DYNAMIC",[676,2376,2348],{},[655,2378,2379,2383,2388],{},[676,2380,2381],{},[106,2382,1736],{},[676,2384,2385],{},[123,2386,2387],{},"STALE",[676,2389,2390],{},"Serving stale data (lock race condition fallback)",[655,2392,2393,2398,2403],{},[676,2394,2395],{},[106,2396,2397],{},"Revalidating",[676,2399,2400],{},[123,2401,2402],{},"REVALIDATING",[676,2404,2405],{},"Serving stale data while another request refreshes cache",[852,2407,2409],{"id":2408},"status-in-responses","Status in responses",[102,2411,1700,2412,2415,2416,2419],{},[123,2413,2414],{},"Quayel-Cache-Status"," header is added to ",[106,2417,2418],{},"every"," response:",[116,2421,2424],{"className":2422,"code":2423,"language":1335},[1333],"HTTP\u002F1.1 200 OK\nQuayel-Cache-Status: HIT\nContent-Type: application\u002Fjson\n...\n\nHTTP\u002F1.1 200 OK\nQuayel-Cache-Status: REVALIDATING\nContent-Type: application\u002Fjson\n...\n\nHTTP\u002F1.1 200 OK\nQuayel-Cache-Status: MISS\nContent-Type: application\u002Fjson\n...\n",[123,2425,2423],{"__ignoreMap":121},[111,2427,2429],{"id":2428},"cdn-cache-control-parsing","CDN Cache-Control parsing",[102,2431,2432,2433,1021],{},"The gateway parses these directives from the upstream ",[123,2434,830],{},[649,2436,2437,2446],{},[652,2438,2439],{},[655,2440,2441,2443],{},[658,2442,1408],{},[658,2444,2445],{},"Effect",[671,2447,2448,2459,2473,2482,2491,2500,2508,2517],{},[655,2449,2450,2454],{},[676,2451,2452],{},[123,2453,1076],{},[676,2455,2456,2457,720],{},"Used as edge TTL (when ",[123,2458,1432],{},[655,2460,2461,2465],{},[676,2462,2463],{},[123,2464,1080],{},[676,2466,2467,2468,2470,2471,720],{},"Fallback edge TTL (when ",[123,2469,1432],{}," and no ",[123,2472,1076],{},[655,2474,2475,2479],{},[676,2476,2477],{},[123,2478,1160],{},[676,2480,2481],{},"SWR window duration (seconds)",[655,2483,2484,2488],{},[676,2485,2486],{},[123,2487,1164],{},[676,2489,2490],{},"SIE window duration (seconds)",[655,2492,2493,2497],{},[676,2494,2495],{},[123,2496,888],{},[676,2498,2499],{},"Response is not cached",[655,2501,2502,2506],{},[676,2503,2504],{},[123,2505,892],{},[676,2507,2499],{},[655,2509,2510,2515],{},[676,2511,2512],{},[123,2513,2514],{},"private",[676,2516,2499],{},[655,2518,2519,2524],{},[676,2520,2521],{},[123,2522,2523],{},"public",[676,2525,2526],{},"Ignored (gateway caches by default)",[852,2528,2530],{"id":2529},"priority-order-for-edge-ttl","Priority order for edge TTL",[102,2532,2533,2534,149],{},"When ",[123,2535,1432],{},[859,2537,2538,2543,2547,2552],{},[862,2539,2540,2542],{},[123,2541,1076],{}," (if present)",[862,2544,2545,2542],{},[123,2546,1080],{},[862,2548,1359,2549,2551],{},[123,2550,447],{}," (fallback)",[862,2553,2554],{},"Not cached (if none present)",[102,2556,2533,2557,149],{},[123,2558,2559],{},"mode: custom",[859,2561,2562,2567,2576,2583],{},[862,2563,1359,2564,2566],{},[123,2565,447],{}," (if provided)",[862,2568,2569,2570,2572,2573,2575],{},"CDN ",[123,2571,1076],{}," (fallback if ",[123,2574,447],{}," missing)",[862,2577,2569,2578,2580,2581,720],{},[123,2579,1080],{}," (fallback if no ",[123,2582,1076],{},[862,2584,2554],{},[111,2586,2588],{"id":2587},"examples","Examples",[852,2590,2592],{"id":2591},"cache-static-assets","Cache static assets",[116,2594,2596],{"className":118,"code":2595,"language":120,"meta":121,"style":121},"{\n  \"id\": \"cache-static\",\n  \"name\": \"Cache Static Assets\",\n  \"enabled\": true,\n  \"conditions\": [\n    { \"left\": \"req.path\", \"operator\": \"regex\", \"value\": \"\\\\.(css|js|png|jpg|svg|woff2?)$\" }\n  ],\n  \"cache\": \"eligible\",\n  \"edge_ttl\": { \"mode\": \"custom\", \"seconds\": 86400 },\n  \"browser_ttl\": { \"mode\": \"custom\", \"seconds\": 3600 },\n  \"cache_key\": { \"mode\": \"default\" },\n  \"statuses\": [200]\n}\n",[123,2597,2598,2602,2620,2638,2650,2662,2716,2720,2738,2779,2820,2848,2864],{"__ignoreMap":121},[126,2599,2600],{"class":128,"line":129},[126,2601,133],{"class":132},[126,2603,2604,2606,2608,2610,2612,2614,2616,2618],{"class":128,"line":136},[126,2605,139],{"class":132},[126,2607,234],{"class":142},[126,2609,146],{"class":132},[126,2611,149],{"class":132},[126,2613,241],{"class":132},[126,2615,245],{"class":244},[126,2617,146],{"class":132},[126,2619,203],{"class":132},[126,2621,2622,2624,2626,2628,2630,2632,2634,2636],{"class":128,"line":155},[126,2623,139],{"class":132},[126,2625,257],{"class":142},[126,2627,146],{"class":132},[126,2629,149],{"class":132},[126,2631,241],{"class":132},[126,2633,266],{"class":244},[126,2635,146],{"class":132},[126,2637,203],{"class":132},[126,2639,2640,2642,2644,2646,2648],{"class":128,"line":171},[126,2641,139],{"class":132},[126,2643,178],{"class":142},[126,2645,146],{"class":132},[126,2647,149],{"class":132},[126,2649,185],{"class":132},[126,2651,2652,2654,2656,2658,2660],{"class":128,"line":188},[126,2653,139],{"class":132},[126,2655,291],{"class":142},[126,2657,146],{"class":132},[126,2659,149],{"class":132},[126,2661,218],{"class":132},[126,2663,2664,2666,2668,2670,2672,2674,2676,2678,2680,2682,2684,2686,2688,2690,2692,2694,2696,2698,2700,2702,2704,2706,2708,2710,2712,2714],{"class":128,"line":206},[126,2665,925],{"class":132},[126,2667,241],{"class":132},[126,2669,313],{"class":161},[126,2671,146],{"class":132},[126,2673,149],{"class":132},[126,2675,241],{"class":132},[126,2677,322],{"class":244},[126,2679,146],{"class":132},[126,2681,570],{"class":132},[126,2683,241],{"class":132},[126,2685,334],{"class":161},[126,2687,146],{"class":132},[126,2689,149],{"class":132},[126,2691,241],{"class":132},[126,2693,343],{"class":244},[126,2695,146],{"class":132},[126,2697,570],{"class":132},[126,2699,241],{"class":132},[126,2701,355],{"class":161},[126,2703,146],{"class":132},[126,2705,149],{"class":132},[126,2707,241],{"class":132},[126,2709,365],{"class":364},[126,2711,368],{"class":244},[126,2713,146],{"class":132},[126,2715,976],{"class":132},[126,2717,2718],{"class":128,"line":221},[126,2719,981],{"class":132},[126,2721,2722,2724,2726,2728,2730,2732,2734,2736],{"class":128,"line":227},[126,2723,139],{"class":132},[126,2725,162],{"class":142},[126,2727,146],{"class":132},[126,2729,149],{"class":132},[126,2731,241],{"class":132},[126,2733,399],{"class":244},[126,2735,146],{"class":132},[126,2737,203],{"class":132},[126,2739,2740,2742,2744,2746,2748,2750,2752,2754,2756,2758,2760,2762,2764,2766,2768,2770,2772,2774,2777],{"class":128,"line":252},[126,2741,139],{"class":132},[126,2743,411],{"class":142},[126,2745,146],{"class":132},[126,2747,149],{"class":132},[126,2749,1253],{"class":132},[126,2751,241],{"class":132},[126,2753,426],{"class":161},[126,2755,146],{"class":132},[126,2757,149],{"class":132},[126,2759,241],{"class":132},[126,2761,435],{"class":244},[126,2763,146],{"class":132},[126,2765,570],{"class":132},[126,2767,241],{"class":132},[126,2769,447],{"class":161},[126,2771,146],{"class":132},[126,2773,149],{"class":132},[126,2775,2776],{"class":177}," 86400",[126,2778,1270],{"class":132},[126,2780,2781,2783,2785,2787,2789,2791,2793,2795,2797,2799,2801,2803,2805,2807,2809,2811,2813,2815,2818],{"class":128,"line":273},[126,2782,139],{"class":132},[126,2784,468],{"class":142},[126,2786,146],{"class":132},[126,2788,149],{"class":132},[126,2790,1253],{"class":132},[126,2792,241],{"class":132},[126,2794,426],{"class":161},[126,2796,146],{"class":132},[126,2798,149],{"class":132},[126,2800,241],{"class":132},[126,2802,435],{"class":244},[126,2804,146],{"class":132},[126,2806,570],{"class":132},[126,2808,241],{"class":132},[126,2810,447],{"class":161},[126,2812,146],{"class":132},[126,2814,149],{"class":132},[126,2816,2817],{"class":177}," 3600",[126,2819,1270],{"class":132},[126,2821,2822,2824,2826,2828,2830,2832,2834,2836,2838,2840,2842,2844,2846],{"class":128,"line":286},[126,2823,139],{"class":132},[126,2825,520],{"class":142},[126,2827,146],{"class":132},[126,2829,149],{"class":132},[126,2831,1253],{"class":132},[126,2833,241],{"class":132},[126,2835,426],{"class":161},[126,2837,146],{"class":132},[126,2839,149],{"class":132},[126,2841,241],{"class":132},[126,2843,542],{"class":244},[126,2845,146],{"class":132},[126,2847,1270],{"class":132},[126,2849,2850,2852,2854,2856,2858,2860,2862],{"class":128,"line":300},[126,2851,139],{"class":132},[126,2853,557],{"class":142},[126,2855,146],{"class":132},[126,2857,149],{"class":132},[126,2859,564],{"class":132},[126,2861,567],{"class":177},[126,2863,1316],{"class":132},[126,2865,2866],{"class":128,"line":306},[126,2867,643],{"class":132},[852,2869,2871],{"id":2870},"cache-api-responses-by-country","Cache API responses by country",[116,2873,2875],{"className":118,"code":2874,"language":120,"meta":121,"style":121},"{\n  \"id\": \"cache-api-geo\",\n  \"name\": \"Cache API by Country\",\n  \"enabled\": true,\n  \"conditions\": [\n    { \"left\": \"req.path\", \"operator\": \"starts_with\", \"value\": \"\u002Fapi\u002Fcontent\u002F\" },\n    { \"left\": \"req.method\", \"operator\": \"equals\", \"value\": \"GET\" }\n  ],\n  \"cache\": \"eligible\",\n  \"edge_ttl\": { \"mode\": \"custom\", \"seconds\": 300 },\n  \"browser_ttl\": { \"mode\": \"custom\", \"seconds\": 60 },\n  \"cache_key\": {\n    \"mode\": \"custom\",\n    \"parts\": [\"ip.country\"]\n  },\n  \"statuses\": [200]\n}\n",[123,2876,2877,2881,2900,2919,2931,2943,2996,3051,3055,3073,3114,3155,3167,3185,3205,3210,3226],{"__ignoreMap":121},[126,2878,2879],{"class":128,"line":129},[126,2880,133],{"class":132},[126,2882,2883,2885,2887,2889,2891,2893,2896,2898],{"class":128,"line":136},[126,2884,139],{"class":132},[126,2886,234],{"class":142},[126,2888,146],{"class":132},[126,2890,149],{"class":132},[126,2892,241],{"class":132},[126,2894,2895],{"class":244},"cache-api-geo",[126,2897,146],{"class":132},[126,2899,203],{"class":132},[126,2901,2902,2904,2906,2908,2910,2912,2915,2917],{"class":128,"line":155},[126,2903,139],{"class":132},[126,2905,257],{"class":142},[126,2907,146],{"class":132},[126,2909,149],{"class":132},[126,2911,241],{"class":132},[126,2913,2914],{"class":244},"Cache API by Country",[126,2916,146],{"class":132},[126,2918,203],{"class":132},[126,2920,2921,2923,2925,2927,2929],{"class":128,"line":171},[126,2922,139],{"class":132},[126,2924,178],{"class":142},[126,2926,146],{"class":132},[126,2928,149],{"class":132},[126,2930,185],{"class":132},[126,2932,2933,2935,2937,2939,2941],{"class":128,"line":188},[126,2934,139],{"class":132},[126,2936,291],{"class":142},[126,2938,146],{"class":132},[126,2940,149],{"class":132},[126,2942,218],{"class":132},[126,2944,2945,2947,2949,2951,2953,2955,2957,2959,2961,2963,2965,2967,2969,2971,2973,2975,2977,2979,2981,2983,2985,2987,2989,2992,2994],{"class":128,"line":206},[126,2946,925],{"class":132},[126,2948,241],{"class":132},[126,2950,313],{"class":161},[126,2952,146],{"class":132},[126,2954,149],{"class":132},[126,2956,241],{"class":132},[126,2958,322],{"class":244},[126,2960,146],{"class":132},[126,2962,570],{"class":132},[126,2964,241],{"class":132},[126,2966,334],{"class":161},[126,2968,146],{"class":132},[126,2970,149],{"class":132},[126,2972,241],{"class":132},[126,2974,954],{"class":244},[126,2976,146],{"class":132},[126,2978,570],{"class":132},[126,2980,241],{"class":132},[126,2982,355],{"class":161},[126,2984,146],{"class":132},[126,2986,149],{"class":132},[126,2988,241],{"class":132},[126,2990,2991],{"class":244},"\u002Fapi\u002Fcontent\u002F",[126,2993,146],{"class":132},[126,2995,1270],{"class":132},[126,2997,2998,3000,3002,3004,3006,3008,3010,3013,3015,3017,3019,3021,3023,3025,3027,3030,3032,3034,3036,3038,3040,3042,3044,3047,3049],{"class":128,"line":221},[126,2999,925],{"class":132},[126,3001,241],{"class":132},[126,3003,313],{"class":161},[126,3005,146],{"class":132},[126,3007,149],{"class":132},[126,3009,241],{"class":132},[126,3011,3012],{"class":244},"req.method",[126,3014,146],{"class":132},[126,3016,570],{"class":132},[126,3018,241],{"class":132},[126,3020,334],{"class":161},[126,3022,146],{"class":132},[126,3024,149],{"class":132},[126,3026,241],{"class":132},[126,3028,3029],{"class":244},"equals",[126,3031,146],{"class":132},[126,3033,570],{"class":132},[126,3035,241],{"class":132},[126,3037,355],{"class":161},[126,3039,146],{"class":132},[126,3041,149],{"class":132},[126,3043,241],{"class":132},[126,3045,3046],{"class":244},"GET",[126,3048,146],{"class":132},[126,3050,976],{"class":132},[126,3052,3053],{"class":128,"line":227},[126,3054,981],{"class":132},[126,3056,3057,3059,3061,3063,3065,3067,3069,3071],{"class":128,"line":252},[126,3058,139],{"class":132},[126,3060,162],{"class":142},[126,3062,146],{"class":132},[126,3064,149],{"class":132},[126,3066,241],{"class":132},[126,3068,399],{"class":244},[126,3070,146],{"class":132},[126,3072,203],{"class":132},[126,3074,3075,3077,3079,3081,3083,3085,3087,3089,3091,3093,3095,3097,3099,3101,3103,3105,3107,3109,3112],{"class":128,"line":273},[126,3076,139],{"class":132},[126,3078,411],{"class":142},[126,3080,146],{"class":132},[126,3082,149],{"class":132},[126,3084,1253],{"class":132},[126,3086,241],{"class":132},[126,3088,426],{"class":161},[126,3090,146],{"class":132},[126,3092,149],{"class":132},[126,3094,241],{"class":132},[126,3096,435],{"class":244},[126,3098,146],{"class":132},[126,3100,570],{"class":132},[126,3102,241],{"class":132},[126,3104,447],{"class":161},[126,3106,146],{"class":132},[126,3108,149],{"class":132},[126,3110,3111],{"class":177}," 300",[126,3113,1270],{"class":132},[126,3115,3116,3118,3120,3122,3124,3126,3128,3130,3132,3134,3136,3138,3140,3142,3144,3146,3148,3150,3153],{"class":128,"line":286},[126,3117,139],{"class":132},[126,3119,468],{"class":142},[126,3121,146],{"class":132},[126,3123,149],{"class":132},[126,3125,1253],{"class":132},[126,3127,241],{"class":132},[126,3129,426],{"class":161},[126,3131,146],{"class":132},[126,3133,149],{"class":132},[126,3135,241],{"class":132},[126,3137,435],{"class":244},[126,3139,146],{"class":132},[126,3141,570],{"class":132},[126,3143,241],{"class":132},[126,3145,447],{"class":161},[126,3147,146],{"class":132},[126,3149,149],{"class":132},[126,3151,3152],{"class":177}," 60",[126,3154,1270],{"class":132},[126,3156,3157,3159,3161,3163,3165],{"class":128,"line":300},[126,3158,139],{"class":132},[126,3160,520],{"class":142},[126,3162,146],{"class":132},[126,3164,149],{"class":132},[126,3166,152],{"class":132},[126,3168,3169,3171,3173,3175,3177,3179,3181,3183],{"class":128,"line":306},[126,3170,158],{"class":132},[126,3172,426],{"class":161},[126,3174,146],{"class":132},[126,3176,149],{"class":132},[126,3178,241],{"class":132},[126,3180,435],{"class":244},[126,3182,146],{"class":132},[126,3184,203],{"class":132},[126,3186,3187,3189,3191,3193,3195,3197,3199,3201,3203],{"class":128,"line":329},[126,3188,158],{"class":132},[126,3190,2138],{"class":161},[126,3192,146],{"class":132},[126,3194,149],{"class":132},[126,3196,564],{"class":132},[126,3198,146],{"class":132},[126,3200,2151],{"class":244},[126,3202,146],{"class":132},[126,3204,1316],{"class":132},[126,3206,3207],{"class":128,"line":350},[126,3208,3209],{"class":132},"  },\n",[126,3211,3212,3214,3216,3218,3220,3222,3224],{"class":128,"line":374},[126,3213,139],{"class":132},[126,3215,557],{"class":142},[126,3217,146],{"class":132},[126,3219,149],{"class":132},[126,3221,564],{"class":132},[126,3223,567],{"class":177},[126,3225,1316],{"class":132},[126,3227,3228],{"class":128,"line":380},[126,3229,643],{"class":132},[852,3231,3233],{"id":3232},"bypass-cache-for-authenticated-requests","Bypass cache for authenticated requests",[116,3235,3237],{"className":118,"code":3236,"language":120,"meta":121,"style":121},"{\n  \"id\": \"bypass-auth\",\n  \"name\": \"Bypass Cache for Auth\",\n  \"enabled\": true,\n  \"conditions\": [\n    { \"left\": \"req.header.Authorization\", \"operator\": \"exists\" }\n  ],\n  \"cache\": \"bypass\"\n}\n",[123,3238,3239,3243,3262,3281,3293,3305,3343,3347,3363],{"__ignoreMap":121},[126,3240,3241],{"class":128,"line":129},[126,3242,133],{"class":132},[126,3244,3245,3247,3249,3251,3253,3255,3258,3260],{"class":128,"line":136},[126,3246,139],{"class":132},[126,3248,234],{"class":142},[126,3250,146],{"class":132},[126,3252,149],{"class":132},[126,3254,241],{"class":132},[126,3256,3257],{"class":244},"bypass-auth",[126,3259,146],{"class":132},[126,3261,203],{"class":132},[126,3263,3264,3266,3268,3270,3272,3274,3277,3279],{"class":128,"line":155},[126,3265,139],{"class":132},[126,3267,257],{"class":142},[126,3269,146],{"class":132},[126,3271,149],{"class":132},[126,3273,241],{"class":132},[126,3275,3276],{"class":244},"Bypass Cache for Auth",[126,3278,146],{"class":132},[126,3280,203],{"class":132},[126,3282,3283,3285,3287,3289,3291],{"class":128,"line":171},[126,3284,139],{"class":132},[126,3286,178],{"class":142},[126,3288,146],{"class":132},[126,3290,149],{"class":132},[126,3292,185],{"class":132},[126,3294,3295,3297,3299,3301,3303],{"class":128,"line":188},[126,3296,139],{"class":132},[126,3298,291],{"class":142},[126,3300,146],{"class":132},[126,3302,149],{"class":132},[126,3304,218],{"class":132},[126,3306,3307,3309,3311,3313,3315,3317,3319,3322,3324,3326,3328,3330,3332,3334,3336,3339,3341],{"class":128,"line":206},[126,3308,925],{"class":132},[126,3310,241],{"class":132},[126,3312,313],{"class":161},[126,3314,146],{"class":132},[126,3316,149],{"class":132},[126,3318,241],{"class":132},[126,3320,3321],{"class":244},"req.header.Authorization",[126,3323,146],{"class":132},[126,3325,570],{"class":132},[126,3327,241],{"class":132},[126,3329,334],{"class":161},[126,3331,146],{"class":132},[126,3333,149],{"class":132},[126,3335,241],{"class":132},[126,3337,3338],{"class":244},"exists",[126,3340,146],{"class":132},[126,3342,976],{"class":132},[126,3344,3345],{"class":128,"line":221},[126,3346,981],{"class":132},[126,3348,3349,3351,3353,3355,3357,3359,3361],{"class":128,"line":227},[126,3350,139],{"class":132},[126,3352,162],{"class":142},[126,3354,146],{"class":132},[126,3356,149],{"class":132},[126,3358,241],{"class":132},[126,3360,895],{"class":244},[126,3362,371],{"class":132},[126,3364,3365],{"class":128,"line":252},[126,3366,643],{"class":132},[852,3368,3370],{"id":3369},"cache-with-origin-ttl-reads-from-cache-control","Cache with origin TTL (reads from Cache-Control)",[116,3372,3374],{"className":118,"code":3373,"language":120,"meta":121,"style":121},"{\n  \"id\": \"cache-origin-ttl\",\n  \"name\": \"Cache with Origin TTL\",\n  \"enabled\": true,\n  \"conditions\": [\n    { \"left\": \"req.method\", \"operator\": \"equals\", \"value\": \"GET\" }\n  ],\n  \"cache\": \"eligible\",\n  \"edge_ttl\": { \"mode\": \"origin\" },\n  \"browser_ttl\": { \"mode\": \"origin\" },\n  \"cache_key\": { \"mode\": \"default\" },\n  \"stale_while_revalidate\": 30,\n  \"stale_if_error\": 120\n}\n",[123,3375,3376,3380,3399,3418,3430,3442,3494,3498,3516,3544,3572,3600,3614,3626],{"__ignoreMap":121},[126,3377,3378],{"class":128,"line":129},[126,3379,133],{"class":132},[126,3381,3382,3384,3386,3388,3390,3392,3395,3397],{"class":128,"line":136},[126,3383,139],{"class":132},[126,3385,234],{"class":142},[126,3387,146],{"class":132},[126,3389,149],{"class":132},[126,3391,241],{"class":132},[126,3393,3394],{"class":244},"cache-origin-ttl",[126,3396,146],{"class":132},[126,3398,203],{"class":132},[126,3400,3401,3403,3405,3407,3409,3411,3414,3416],{"class":128,"line":155},[126,3402,139],{"class":132},[126,3404,257],{"class":142},[126,3406,146],{"class":132},[126,3408,149],{"class":132},[126,3410,241],{"class":132},[126,3412,3413],{"class":244},"Cache with Origin TTL",[126,3415,146],{"class":132},[126,3417,203],{"class":132},[126,3419,3420,3422,3424,3426,3428],{"class":128,"line":171},[126,3421,139],{"class":132},[126,3423,178],{"class":142},[126,3425,146],{"class":132},[126,3427,149],{"class":132},[126,3429,185],{"class":132},[126,3431,3432,3434,3436,3438,3440],{"class":128,"line":188},[126,3433,139],{"class":132},[126,3435,291],{"class":142},[126,3437,146],{"class":132},[126,3439,149],{"class":132},[126,3441,218],{"class":132},[126,3443,3444,3446,3448,3450,3452,3454,3456,3458,3460,3462,3464,3466,3468,3470,3472,3474,3476,3478,3480,3482,3484,3486,3488,3490,3492],{"class":128,"line":206},[126,3445,925],{"class":132},[126,3447,241],{"class":132},[126,3449,313],{"class":161},[126,3451,146],{"class":132},[126,3453,149],{"class":132},[126,3455,241],{"class":132},[126,3457,3012],{"class":244},[126,3459,146],{"class":132},[126,3461,570],{"class":132},[126,3463,241],{"class":132},[126,3465,334],{"class":161},[126,3467,146],{"class":132},[126,3469,149],{"class":132},[126,3471,241],{"class":132},[126,3473,3029],{"class":244},[126,3475,146],{"class":132},[126,3477,570],{"class":132},[126,3479,241],{"class":132},[126,3481,355],{"class":161},[126,3483,146],{"class":132},[126,3485,149],{"class":132},[126,3487,241],{"class":132},[126,3489,3046],{"class":244},[126,3491,146],{"class":132},[126,3493,976],{"class":132},[126,3495,3496],{"class":128,"line":221},[126,3497,981],{"class":132},[126,3499,3500,3502,3504,3506,3508,3510,3512,3514],{"class":128,"line":227},[126,3501,139],{"class":132},[126,3503,162],{"class":142},[126,3505,146],{"class":132},[126,3507,149],{"class":132},[126,3509,241],{"class":132},[126,3511,399],{"class":244},[126,3513,146],{"class":132},[126,3515,203],{"class":132},[126,3517,3518,3520,3522,3524,3526,3528,3530,3532,3534,3536,3538,3540,3542],{"class":128,"line":252},[126,3519,139],{"class":132},[126,3521,411],{"class":142},[126,3523,146],{"class":132},[126,3525,149],{"class":132},[126,3527,1253],{"class":132},[126,3529,241],{"class":132},[126,3531,426],{"class":161},[126,3533,146],{"class":132},[126,3535,149],{"class":132},[126,3537,241],{"class":132},[126,3539,1057],{"class":244},[126,3541,146],{"class":132},[126,3543,1270],{"class":132},[126,3545,3546,3548,3550,3552,3554,3556,3558,3560,3562,3564,3566,3568,3570],{"class":128,"line":273},[126,3547,139],{"class":132},[126,3549,468],{"class":142},[126,3551,146],{"class":132},[126,3553,149],{"class":132},[126,3555,1253],{"class":132},[126,3557,241],{"class":132},[126,3559,426],{"class":161},[126,3561,146],{"class":132},[126,3563,149],{"class":132},[126,3565,241],{"class":132},[126,3567,1057],{"class":244},[126,3569,146],{"class":132},[126,3571,1270],{"class":132},[126,3573,3574,3576,3578,3580,3582,3584,3586,3588,3590,3592,3594,3596,3598],{"class":128,"line":286},[126,3575,139],{"class":132},[126,3577,520],{"class":142},[126,3579,146],{"class":132},[126,3581,149],{"class":132},[126,3583,1253],{"class":132},[126,3585,241],{"class":132},[126,3587,426],{"class":161},[126,3589,146],{"class":132},[126,3591,149],{"class":132},[126,3593,241],{"class":132},[126,3595,542],{"class":244},[126,3597,146],{"class":132},[126,3599,1270],{"class":132},[126,3601,3602,3604,3606,3608,3610,3612],{"class":128,"line":300},[126,3603,139],{"class":132},[126,3605,589],{"class":142},[126,3607,146],{"class":132},[126,3609,149],{"class":132},[126,3611,596],{"class":177},[126,3613,203],{"class":132},[126,3615,3616,3618,3620,3622,3624],{"class":128,"line":306},[126,3617,139],{"class":132},[126,3619,606],{"class":142},[126,3621,146],{"class":132},[126,3623,149],{"class":132},[126,3625,613],{"class":177},[126,3627,3628],{"class":128,"line":329},[126,3629,643],{"class":132},[102,3631,3632],{},"When the origin responds with:",[116,3634,3636],{"className":1831,"code":3635,"language":1833,"meta":121,"style":121},"Cache-Control: s-maxage=120\n",[123,3637,3638],{"__ignoreMap":121},[126,3639,3640],{"class":128,"line":129},[126,3641,3635],{},[102,3643,3644],{},"The gateway:",[1807,3646,3647,3652,3655],{},[862,3648,3649,3650,720],{},"Caches for 120 seconds (from origin ",[123,3651,1076],{},[862,3653,3654],{},"Serves stale for up to 30s while revalidating (from gateway config)",[862,3656,3657],{},"Serves stale for up to 120s if origin errors (from gateway config)",[1550,3659,3660,3661,1161,3663,3665],{},"Gateway-level ",[123,3662,589],{},[123,3664,606],{}," override origin headers. If the origin also sends these directives, the gateway config takes priority.",[852,3667,3669],{"id":3668},"multi-rule-cache-strategy","Multi-rule cache strategy",[116,3671,3673],{"className":118,"code":3672,"language":120,"meta":121,"style":121},"{\n  \"rules\": [\n    {\n      \"id\": \"bypass-api\",\n      \"name\": \"Bypass API Cache\",\n      \"enabled\": true,\n      \"conditions\": [\n        { \"left\": \"req.path\", \"operator\": \"starts_with\", \"value\": \"\u002Fapi\u002F\" }\n      ],\n      \"cache\": \"bypass\"\n    },\n    {\n      \"id\": \"cache-pages\",\n      \"name\": \"Cache Pages\",\n      \"enabled\": true,\n      \"conditions\": [\n        { \"left\": \"req.method\", \"operator\": \"equals\", \"value\": \"GET\" }\n      ],\n      \"cache\": \"eligible\",\n      \"edge_ttl\": { \"mode\": \"custom\", \"seconds\": 600 },\n      \"browser_ttl\": { \"mode\": \"custom\", \"seconds\": 60 },\n      \"cache_key\": {\n        \"mode\": \"custom\",\n        \"parts\": [\"ip.country\"]\n      },\n      \"statuses\": [200, 404]\n    }\n  ]\n}\n",[123,3674,3675,3679,3691,3696,3715,3734,3746,3758,3811,3816,3832,3837,3841,3860,3879,3891,3903,3955,3959,3977,4018,4058,4070,4089,4109,4114,4134,4138,4143],{"__ignoreMap":121},[126,3676,3677],{"class":128,"line":129},[126,3678,133],{"class":132},[126,3680,3681,3683,3685,3687,3689],{"class":128,"line":136},[126,3682,139],{"class":132},[126,3684,211],{"class":142},[126,3686,146],{"class":132},[126,3688,149],{"class":132},[126,3690,218],{"class":132},[126,3692,3693],{"class":128,"line":155},[126,3694,3695],{"class":132},"    {\n",[126,3697,3698,3700,3702,3704,3706,3708,3711,3713],{"class":128,"line":171},[126,3699,174],{"class":132},[126,3701,234],{"class":161},[126,3703,146],{"class":132},[126,3705,149],{"class":132},[126,3707,241],{"class":132},[126,3709,3710],{"class":244},"bypass-api",[126,3712,146],{"class":132},[126,3714,203],{"class":132},[126,3716,3717,3719,3721,3723,3725,3727,3730,3732],{"class":128,"line":188},[126,3718,174],{"class":132},[126,3720,257],{"class":161},[126,3722,146],{"class":132},[126,3724,149],{"class":132},[126,3726,241],{"class":132},[126,3728,3729],{"class":244},"Bypass API Cache",[126,3731,146],{"class":132},[126,3733,203],{"class":132},[126,3735,3736,3738,3740,3742,3744],{"class":128,"line":206},[126,3737,174],{"class":132},[126,3739,178],{"class":161},[126,3741,146],{"class":132},[126,3743,149],{"class":132},[126,3745,185],{"class":132},[126,3747,3748,3750,3752,3754,3756],{"class":128,"line":221},[126,3749,174],{"class":132},[126,3751,291],{"class":161},[126,3753,146],{"class":132},[126,3755,149],{"class":132},[126,3757,218],{"class":132},[126,3759,3760,3763,3765,3767,3769,3771,3773,3775,3777,3779,3781,3783,3785,3787,3789,3791,3793,3795,3797,3799,3801,3803,3805,3807,3809],{"class":128,"line":227},[126,3761,3762],{"class":132},"        {",[126,3764,241],{"class":132},[126,3766,313],{"class":177},[126,3768,146],{"class":132},[126,3770,149],{"class":132},[126,3772,241],{"class":132},[126,3774,322],{"class":244},[126,3776,146],{"class":132},[126,3778,570],{"class":132},[126,3780,241],{"class":132},[126,3782,334],{"class":177},[126,3784,146],{"class":132},[126,3786,149],{"class":132},[126,3788,241],{"class":132},[126,3790,954],{"class":244},[126,3792,146],{"class":132},[126,3794,570],{"class":132},[126,3796,241],{"class":132},[126,3798,355],{"class":177},[126,3800,146],{"class":132},[126,3802,149],{"class":132},[126,3804,241],{"class":132},[126,3806,971],{"class":244},[126,3808,146],{"class":132},[126,3810,976],{"class":132},[126,3812,3813],{"class":128,"line":252},[126,3814,3815],{"class":132},"      ],\n",[126,3817,3818,3820,3822,3824,3826,3828,3830],{"class":128,"line":273},[126,3819,174],{"class":132},[126,3821,162],{"class":161},[126,3823,146],{"class":132},[126,3825,149],{"class":132},[126,3827,241],{"class":132},[126,3829,895],{"class":244},[126,3831,371],{"class":132},[126,3833,3834],{"class":128,"line":286},[126,3835,3836],{"class":132},"    },\n",[126,3838,3839],{"class":128,"line":300},[126,3840,3695],{"class":132},[126,3842,3843,3845,3847,3849,3851,3853,3856,3858],{"class":128,"line":306},[126,3844,174],{"class":132},[126,3846,234],{"class":161},[126,3848,146],{"class":132},[126,3850,149],{"class":132},[126,3852,241],{"class":132},[126,3854,3855],{"class":244},"cache-pages",[126,3857,146],{"class":132},[126,3859,203],{"class":132},[126,3861,3862,3864,3866,3868,3870,3872,3875,3877],{"class":128,"line":329},[126,3863,174],{"class":132},[126,3865,257],{"class":161},[126,3867,146],{"class":132},[126,3869,149],{"class":132},[126,3871,241],{"class":132},[126,3873,3874],{"class":244},"Cache Pages",[126,3876,146],{"class":132},[126,3878,203],{"class":132},[126,3880,3881,3883,3885,3887,3889],{"class":128,"line":350},[126,3882,174],{"class":132},[126,3884,178],{"class":161},[126,3886,146],{"class":132},[126,3888,149],{"class":132},[126,3890,185],{"class":132},[126,3892,3893,3895,3897,3899,3901],{"class":128,"line":374},[126,3894,174],{"class":132},[126,3896,291],{"class":161},[126,3898,146],{"class":132},[126,3900,149],{"class":132},[126,3902,218],{"class":132},[126,3904,3905,3907,3909,3911,3913,3915,3917,3919,3921,3923,3925,3927,3929,3931,3933,3935,3937,3939,3941,3943,3945,3947,3949,3951,3953],{"class":128,"line":380},[126,3906,3762],{"class":132},[126,3908,241],{"class":132},[126,3910,313],{"class":177},[126,3912,146],{"class":132},[126,3914,149],{"class":132},[126,3916,241],{"class":132},[126,3918,3012],{"class":244},[126,3920,146],{"class":132},[126,3922,570],{"class":132},[126,3924,241],{"class":132},[126,3926,334],{"class":177},[126,3928,146],{"class":132},[126,3930,149],{"class":132},[126,3932,241],{"class":132},[126,3934,3029],{"class":244},[126,3936,146],{"class":132},[126,3938,570],{"class":132},[126,3940,241],{"class":132},[126,3942,355],{"class":177},[126,3944,146],{"class":132},[126,3946,149],{"class":132},[126,3948,241],{"class":132},[126,3950,3046],{"class":244},[126,3952,146],{"class":132},[126,3954,976],{"class":132},[126,3956,3957],{"class":128,"line":386},[126,3958,3815],{"class":132},[126,3960,3961,3963,3965,3967,3969,3971,3973,3975],{"class":128,"line":406},[126,3962,174],{"class":132},[126,3964,162],{"class":161},[126,3966,146],{"class":132},[126,3968,149],{"class":132},[126,3970,241],{"class":132},[126,3972,399],{"class":244},[126,3974,146],{"class":132},[126,3976,203],{"class":132},[126,3978,3979,3981,3983,3985,3987,3989,3991,3993,3995,3997,3999,4001,4003,4005,4007,4009,4011,4013,4016],{"class":128,"line":420},[126,3980,174],{"class":132},[126,3982,411],{"class":161},[126,3984,146],{"class":132},[126,3986,149],{"class":132},[126,3988,1253],{"class":132},[126,3990,241],{"class":132},[126,3992,426],{"class":177},[126,3994,146],{"class":132},[126,3996,149],{"class":132},[126,3998,241],{"class":132},[126,4000,435],{"class":244},[126,4002,146],{"class":132},[126,4004,570],{"class":132},[126,4006,241],{"class":132},[126,4008,447],{"class":177},[126,4010,146],{"class":132},[126,4012,149],{"class":132},[126,4014,4015],{"class":177}," 600",[126,4017,1270],{"class":132},[126,4019,4020,4022,4024,4026,4028,4030,4032,4034,4036,4038,4040,4042,4044,4046,4048,4050,4052,4054,4056],{"class":128,"line":442},[126,4021,174],{"class":132},[126,4023,468],{"class":161},[126,4025,146],{"class":132},[126,4027,149],{"class":132},[126,4029,1253],{"class":132},[126,4031,241],{"class":132},[126,4033,426],{"class":177},[126,4035,146],{"class":132},[126,4037,149],{"class":132},[126,4039,241],{"class":132},[126,4041,435],{"class":244},[126,4043,146],{"class":132},[126,4045,570],{"class":132},[126,4047,241],{"class":132},[126,4049,447],{"class":177},[126,4051,146],{"class":132},[126,4053,149],{"class":132},[126,4055,3152],{"class":177},[126,4057,1270],{"class":132},[126,4059,4060,4062,4064,4066,4068],{"class":128,"line":457},[126,4061,174],{"class":132},[126,4063,520],{"class":161},[126,4065,146],{"class":132},[126,4067,149],{"class":132},[126,4069,152],{"class":132},[126,4071,4072,4075,4077,4079,4081,4083,4085,4087],{"class":128,"line":463},[126,4073,4074],{"class":132},"        \"",[126,4076,426],{"class":177},[126,4078,146],{"class":132},[126,4080,149],{"class":132},[126,4082,241],{"class":132},[126,4084,435],{"class":244},[126,4086,146],{"class":132},[126,4088,203],{"class":132},[126,4090,4091,4093,4095,4097,4099,4101,4103,4105,4107],{"class":128,"line":477},[126,4092,4074],{"class":132},[126,4094,2138],{"class":177},[126,4096,146],{"class":132},[126,4098,149],{"class":132},[126,4100,564],{"class":132},[126,4102,146],{"class":132},[126,4104,2151],{"class":244},[126,4106,146],{"class":132},[126,4108,1316],{"class":132},[126,4110,4111],{"class":128,"line":496},[126,4112,4113],{"class":132},"      },\n",[126,4115,4116,4118,4120,4122,4124,4126,4128,4130,4132],{"class":128,"line":510},[126,4117,174],{"class":132},[126,4119,557],{"class":161},[126,4121,146],{"class":132},[126,4123,149],{"class":132},[126,4125,564],{"class":132},[126,4127,567],{"class":177},[126,4129,570],{"class":132},[126,4131,578],{"class":177},[126,4133,1316],{"class":132},[126,4135,4136],{"class":128,"line":515},[126,4137,631],{"class":132},[126,4139,4140],{"class":128,"line":529},[126,4141,4142],{"class":132},"  ]\n",[126,4144,4145],{"class":128,"line":547},[126,4146,643],{"class":132},[111,4148,4150],{"id":4149},"log-output","Log output",[116,4152,4154],{"className":118,"code":4153,"language":120,"meta":121,"style":121},"{\n  \"cache\": {\n    \"rule_id\": \"cache-static\",\n    \"status\": \"HIT\",\n    \"key_hash\": \"a1b2c3d4e5f6...\"\n  }\n}\n",[123,4155,4156,4160,4172,4191,4210,4228,4232],{"__ignoreMap":121},[126,4157,4158],{"class":128,"line":129},[126,4159,133],{"class":132},[126,4161,4162,4164,4166,4168,4170],{"class":128,"line":136},[126,4163,139],{"class":132},[126,4165,162],{"class":142},[126,4167,146],{"class":132},[126,4169,149],{"class":132},[126,4171,152],{"class":132},[126,4173,4174,4176,4179,4181,4183,4185,4187,4189],{"class":128,"line":155},[126,4175,158],{"class":132},[126,4177,4178],{"class":161},"rule_id",[126,4180,146],{"class":132},[126,4182,149],{"class":132},[126,4184,241],{"class":132},[126,4186,245],{"class":244},[126,4188,146],{"class":132},[126,4190,203],{"class":132},[126,4192,4193,4195,4198,4200,4202,4204,4206,4208],{"class":128,"line":171},[126,4194,158],{"class":132},[126,4196,4197],{"class":161},"status",[126,4199,146],{"class":132},[126,4201,149],{"class":132},[126,4203,241],{"class":132},[126,4205,2315],{"class":244},[126,4207,146],{"class":132},[126,4209,203],{"class":132},[126,4211,4212,4214,4217,4219,4221,4223,4226],{"class":128,"line":188},[126,4213,158],{"class":132},[126,4215,4216],{"class":161},"key_hash",[126,4218,146],{"class":132},[126,4220,149],{"class":132},[126,4222,241],{"class":132},[126,4224,4225],{"class":244},"a1b2c3d4e5f6...",[126,4227,371],{"class":132},[126,4229,4230],{"class":128,"line":206},[126,4231,637],{"class":132},[126,4233,4234],{"class":128,"line":221},[126,4235,643],{"class":132},[852,4237,4239],{"id":4238},"monitoring-revalidation","Monitoring revalidation",[116,4241,4245],{"className":4242,"code":4243,"language":4244,"meta":121,"style":121},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Count revalidation events (concurrent stale serving)\ncat access.jsonl | jq 'select(.cache.status == \"REVALIDATING\")' | wc -l\n\n# Count stale fallbacks (lock race condition)\ncat access.jsonl | jq 'select(.cache.status == \"STALE\")' | wc -l\n\n# Cache hit rate (excluding NONE)\ntotal=$(cat access.jsonl | jq 'select(.cache.status != \"NONE\")' | wc -l)\nhits=$(cat access.jsonl | jq 'select(.cache.status == \"HIT\")' | wc -l)\necho \"Cache hit rate: $(echo \"scale=2; $hits * 100 \u002F $total\" | bc)%\"\n","bash",[123,4246,4247,4253,4284,4290,4295,4318,4322,4327,4360,4390],{"__ignoreMap":121},[126,4248,4249],{"class":128,"line":129},[126,4250,4252],{"class":4251},"sHwdD","# Count revalidation events (concurrent stale serving)\n",[126,4254,4255,4258,4261,4264,4267,4270,4273,4276,4278,4281],{"class":128,"line":136},[126,4256,4257],{"class":161},"cat",[126,4259,4260],{"class":244}," access.jsonl",[126,4262,4263],{"class":132}," |",[126,4265,4266],{"class":161}," jq",[126,4268,4269],{"class":132}," '",[126,4271,4272],{"class":244},"select(.cache.status == \"REVALIDATING\")",[126,4274,4275],{"class":132},"'",[126,4277,4263],{"class":132},[126,4279,4280],{"class":161}," wc",[126,4282,4283],{"class":244}," -l\n",[126,4285,4286],{"class":128,"line":155},[126,4287,4289],{"emptyLinePlaceholder":4288},true,"\n",[126,4291,4292],{"class":128,"line":171},[126,4293,4294],{"class":4251},"# Count stale fallbacks (lock race condition)\n",[126,4296,4297,4299,4301,4303,4305,4307,4310,4312,4314,4316],{"class":128,"line":188},[126,4298,4257],{"class":161},[126,4300,4260],{"class":244},[126,4302,4263],{"class":132},[126,4304,4266],{"class":161},[126,4306,4269],{"class":132},[126,4308,4309],{"class":244},"select(.cache.status == \"STALE\")",[126,4311,4275],{"class":132},[126,4313,4263],{"class":132},[126,4315,4280],{"class":161},[126,4317,4283],{"class":244},[126,4319,4320],{"class":128,"line":206},[126,4321,4289],{"emptyLinePlaceholder":4288},[126,4323,4324],{"class":128,"line":221},[126,4325,4326],{"class":4251},"# Cache hit rate (excluding NONE)\n",[126,4328,4329,4332,4335,4337,4339,4341,4343,4345,4348,4350,4352,4354,4357],{"class":128,"line":227},[126,4330,4331],{"class":364},"total",[126,4333,4334],{"class":132},"=$(",[126,4336,4257],{"class":161},[126,4338,4260],{"class":244},[126,4340,4263],{"class":132},[126,4342,4266],{"class":161},[126,4344,4269],{"class":132},[126,4346,4347],{"class":244},"select(.cache.status != \"NONE\")",[126,4349,4275],{"class":132},[126,4351,4263],{"class":132},[126,4353,4280],{"class":161},[126,4355,4356],{"class":244}," -l",[126,4358,4359],{"class":132},")\n",[126,4361,4362,4365,4367,4369,4371,4373,4375,4377,4380,4382,4384,4386,4388],{"class":128,"line":252},[126,4363,4364],{"class":364},"hits",[126,4366,4334],{"class":132},[126,4368,4257],{"class":161},[126,4370,4260],{"class":244},[126,4372,4263],{"class":132},[126,4374,4266],{"class":161},[126,4376,4269],{"class":132},[126,4378,4379],{"class":244},"select(.cache.status == \"HIT\")",[126,4381,4275],{"class":132},[126,4383,4263],{"class":132},[126,4385,4280],{"class":161},[126,4387,4356],{"class":244},[126,4389,4359],{"class":132},[126,4391,4392,4396,4398,4401,4404,4406,4408,4411,4414,4417,4420,4422,4424,4427,4429,4432],{"class":128,"line":273},[126,4393,4395],{"class":4394},"s2Zo4","echo",[126,4397,241],{"class":132},[126,4399,4400],{"class":244},"Cache hit rate: ",[126,4402,4403],{"class":132},"$(",[126,4405,4395],{"class":4394},[126,4407,241],{"class":132},[126,4409,4410],{"class":244},"scale=2; ",[126,4412,4413],{"class":364},"$hits",[126,4415,4416],{"class":244}," * 100 \u002F ",[126,4418,4419],{"class":364},"$total",[126,4421,146],{"class":132},[126,4423,4263],{"class":132},[126,4425,4426],{"class":161}," bc",[126,4428,720],{"class":132},[126,4430,4431],{"class":244},"%",[126,4433,371],{"class":132},[111,4435,4437],{"id":4436},"cacheability-rules","Cacheability rules",[102,4439,4440],{},"A response is cached only if ALL of these are true:",[859,4442,4443,4448,4453,4458,4466],{},[862,4444,4445,4446,867],{},"Response status code is in the ",[123,4447,557],{},[862,4449,4450,4451],{},"Response body size ≤ ",[123,4452,193],{},[862,4454,875,4455,4457],{},[123,4456,878],{}," header present",[862,4459,875,4460,885,4462,889,4464],{},[123,4461,884],{},[123,4463,888],{},[123,4465,892],{},[862,4467,4468],{},"Edge TTL is not zero",[111,4470,4472],{"id":4471},"performance","Performance",[649,4474,4475,4485],{},[652,4476,4477],{},[655,4478,4479,4482],{},[658,4480,4481],{},"Metric",[658,4483,4484],{},"Value",[671,4486,4487,4495,4502,4510,4518,4528],{},[655,4488,4489,4492],{},[676,4490,4491],{},"Cache lookup",[676,4493,4494],{},"O(1) — DashMap",[655,4496,4497,4500],{},[676,4498,4499],{},"Cache store",[676,4501,4494],{},[655,4503,4504,4507],{},[676,4505,4506],{},"Key hash",[676,4508,4509],{},"FxHash (fast, non-cryptographic)",[655,4511,4512,4515],{},[676,4513,4514],{},"Memory per entry",[676,4516,4517],{},"body_size + ~200 bytes overhead",[655,4519,4520,4523],{},[676,4521,4522],{},"Max entries",[676,4524,4525,4526,720],{},"Unlimited (bounded by ",[123,4527,193],{},[655,4529,4530,4533],{},[676,4531,4532],{},"Lock overhead",[676,4534,4535,4536,4539],{},"One ",[123,4537,4538],{},"Arc\u003CMutex\u003C()>>"," per active revalidation",[111,4541,4543],{"id":4542},"notes","Notes",[1807,4545,4546,4553,4556,4559,4567,4570],{},[862,4547,4548,4549,4552],{},"Cache is ",[106,4550,4551],{},"in-memory only"," — entries are lost on restart",[862,4554,4555],{},"Each gateway instance has its own cache (no shared cache)",[862,4557,4558],{},"Rules are evaluated in order — first match wins",[862,4560,1700,4561,4563,4564,4566],{},[123,4562,895],{}," rule should come before ",[123,4565,399],{}," rules for the same paths",[862,4568,4569],{},"Only GET and HEAD requests are cached",[862,4571,4572],{},"The revalidation lock is per-key — different cache keys can revalidate concurrently",[4574,4575,4576],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .su27w, html code.shiki .su27w{--shiki-light:#916B53;--shiki-default:#916B53;--shiki-dark:#916B53}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":121,"searchDepth":136,"depth":136,"links":4578},[4579,4580,4581,4585,4589,4597,4603,4609,4614,4619,4620,4623,4626,4633,4636,4637,4638],{"id":113,"depth":136,"text":114},{"id":646,"depth":136,"text":647},{"id":849,"depth":136,"text":850,"children":4582},[4583,4584],{"id":399,"depth":155,"text":854},{"id":895,"depth":155,"text":896},{"id":1004,"depth":136,"text":1005,"children":4586},[4587,4588],{"id":1011,"depth":155,"text":1012},{"id":1087,"depth":155,"text":1088},{"id":1153,"depth":136,"text":1154,"children":4590},[4591,4592,4593,4594,4595,4596],{"id":1168,"depth":155,"text":1169},{"id":1323,"depth":155,"text":1324},{"id":1340,"depth":155,"text":1341},{"id":1395,"depth":155,"text":1396},{"id":1475,"depth":155,"text":1476},{"id":1485,"depth":155,"text":1486},{"id":1561,"depth":136,"text":1562,"children":4598},[4599,4600,4601,4602],{"id":1572,"depth":155,"text":1573},{"id":1582,"depth":155,"text":1583},{"id":1642,"depth":155,"text":1643},{"id":1725,"depth":155,"text":1726},{"id":1751,"depth":136,"text":1752,"children":4604},[4605,4606,4607,4608],{"id":1760,"depth":155,"text":1761},{"id":1770,"depth":155,"text":1771},{"id":1798,"depth":155,"text":1799},{"id":1824,"depth":155,"text":1825},{"id":1851,"depth":136,"text":1852,"children":4610},[4611,4612,4613],{"id":1861,"depth":155,"text":1862},{"id":1913,"depth":155,"text":1012},{"id":1965,"depth":155,"text":1088},{"id":2030,"depth":136,"text":2031,"children":4615},[4616,4617,4618],{"id":2034,"depth":155,"text":2035},{"id":2089,"depth":155,"text":1088},{"id":2186,"depth":155,"text":2187},{"id":2261,"depth":136,"text":1573},{"id":2270,"depth":136,"text":2271,"children":4621},[4622],{"id":2408,"depth":155,"text":2409},{"id":2428,"depth":136,"text":2429,"children":4624},[4625],{"id":2529,"depth":155,"text":2530},{"id":2587,"depth":136,"text":2588,"children":4627},[4628,4629,4630,4631,4632],{"id":2591,"depth":155,"text":2592},{"id":2870,"depth":155,"text":2871},{"id":3232,"depth":155,"text":3233},{"id":3369,"depth":155,"text":3370},{"id":3668,"depth":155,"text":3669},{"id":4149,"depth":136,"text":4150,"children":4634},[4635],{"id":4238,"depth":155,"text":4239},{"id":4436,"depth":136,"text":4437},{"id":4471,"depth":136,"text":4472},{"id":4542,"depth":136,"text":4543},"Edge caching with TTL, custom keys, stale-while-revalidate, stale-if-error, and singleflight revalidation.","md",null,{},{"icon":57},{"title":54,"description":4639},"cZ_zE5AzHxrX7JluKAysI_JuS4dLJXOkE1h9SIvvcBE",[4647,4649],{"title":49,"path":50,"stem":51,"description":4648,"icon":52,"children":-1},"Sliding-window request quotas per IP, header, JWT claim, or composite key.",{"title":59,"path":60,"stem":61,"description":4650,"icon":62,"children":-1},"Upstream routing with round-robin, weighted, least-connections, fast-response, and sticky session algorithms.",1791649767383]