[{"data":1,"prerenderedAt":1937},["ShallowReactive",2],{"navigation":3,"/actix-web/backends":240,"/actix-web/backends-surround":1932},[4,34,66,87,106,145,166,176,204],{"title":5,"path":6,"stem":7,"children":8,"icon":32,"defaultOpen":33},"Getting Started","/getting-started","1.getting-started/1.index",[9,12,17,22,27],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-info",{"title":13,"path":14,"stem":15,"icon":16},"Installation","/getting-started/installation","1.getting-started/2.installation","i-lucide-download",{"title":18,"path":19,"stem":20,"icon":21},"Quickstart (Local)","/getting-started/quickstart-local","1.getting-started/3.quickstart-local","i-lucide-zap",{"title":23,"path":24,"stem":25,"icon":26},"Quickstart (Redis)","/getting-started/quickstart-redis","1.getting-started/4.quickstart-redis","i-lucide-database",{"title":28,"path":29,"stem":30,"icon":31},"Quickstart (Hybrid)","/getting-started/quickstart-hybrid","1.getting-started/5.quickstart-hybrid","i-lucide-arrow-left-right","i-lucide-rocket",true,{"title":35,"icon":36,"defaultOpen":33,"path":37,"stem":38,"children":39,"page":65},"Concepts","i-lucide-lightbulb","/concepts","2.concepts",[40,45,50,55,60],{"title":41,"path":42,"stem":43,"icon":44},"Keys","/concepts/keys","2.concepts/1.keys","i-lucide-key-round",{"title":46,"path":47,"stem":48,"icon":49},"Rate Limits","/concepts/rate-limits","2.concepts/2.rate-limits","i-lucide-badge-percent",{"title":51,"path":52,"stem":53,"icon":54},"Sliding Windows","/concepts/sliding-windows","2.concepts/3.sliding-windows","i-lucide-timer-reset",{"title":56,"path":57,"stem":58,"icon":59},"Decisions","/concepts/decisions","2.concepts/4.decisions","i-lucide-check-check",{"title":61,"path":62,"stem":63,"icon":64},"Configuration Types","/concepts/configuration-types","2.concepts/5.configuration-types","i-lucide-box",false,{"title":67,"icon":68,"defaultOpen":33,"path":69,"stem":70,"children":71,"page":65},"Strategies","i-lucide-git-branch","/strategies","3.strategies",[72,77,82],{"title":73,"path":74,"stem":75,"icon":76},"Absolute","/strategies/absolute","3.strategies/1.absolute","i-lucide-shield",{"title":78,"path":79,"stem":80,"icon":81},"Suppressed","/strategies/suppressed","3.strategies/2.suppressed","i-lucide-activity",{"title":83,"path":84,"stem":85,"icon":86},"How Suppression Works","/strategies/how-suppression-works","3.strategies/3.how-suppression-works","i-lucide-function-square",{"title":88,"icon":89,"defaultOpen":33,"path":90,"stem":91,"children":92,"page":65},"Providers","i-lucide-layers","/providers","4.providers",[93,98,102],{"title":94,"path":95,"stem":96,"icon":97},"Local","/providers/local","4.providers/1.local","i-lucide-cpu",{"title":99,"path":100,"stem":101,"icon":26},"Redis","/providers/redis","4.providers/2.redis",{"title":103,"path":104,"stem":105,"icon":31},"Hybrid","/providers/hybrid","4.providers/3.hybrid",{"title":107,"path":108,"stem":109,"children":110,"icon":76,"defaultOpen":65},"Actix Web","/actix-web","5.actix-web/1.index",[111,113,118,122,127,131,136,140],{"title":112,"path":108,"stem":109,"icon":76},"Overview",{"title":114,"path":115,"stem":116,"icon":117},"Client IPs","/actix-web/client-ips","5.actix-web/2.client-ips","i-lucide-network",{"title":119,"path":120,"stem":121,"icon":44},"Keys and custom extractors","/actix-web/keys","5.actix-web/3.keys",{"title":123,"path":124,"stem":125,"icon":126},"Limits","/actix-web/limits","5.actix-web/4.limits","i-lucide-gauge",{"title":128,"path":129,"stem":130,"icon":26},"Backends","/actix-web/backends","5.actix-web/5.backends",{"title":132,"path":133,"stem":134,"icon":135},"Responses","/actix-web/responses","5.actix-web/6.responses","i-lucide-reply",{"title":137,"path":138,"stem":139,"icon":81},"Observability","/actix-web/observability","5.actix-web/7.observability",{"title":141,"path":142,"stem":143,"icon":144},"Performance","/actix-web/performance","5.actix-web/8.performance","i-lucide-timer",{"title":146,"icon":147,"defaultOpen":65,"path":148,"stem":149,"children":150,"page":65},"Guides","i-lucide-map","/guides","5.guides",[151,156,161],{"title":152,"path":153,"stem":154,"icon":155},"Configuration","/guides/configuration","5.guides/1.configuration","i-lucide-sliders-horizontal",{"title":157,"path":158,"stem":159,"icon":160},"Cleanup","/guides/cleanup","5.guides/2.cleanup","i-lucide-trash-2",{"title":162,"path":163,"stem":164,"icon":165},"Troubleshooting","/guides/troubleshooting","5.guides/4.troubleshooting","i-lucide-wrench",{"title":167,"icon":168,"defaultOpen":65,"path":169,"stem":170,"children":171,"page":65},"Reference","i-lucide-file-text","/reference","6.reference",[172],{"title":173,"path":174,"stem":175,"icon":168},"API Reference Guide","/reference/api","6.reference/1.api",{"title":177,"icon":126,"defaultOpen":65,"path":178,"stem":179,"children":180,"page":65},"Benchmarks","/benchmarks","7.benchmarks",[181,186,190],{"title":182,"path":183,"stem":184,"icon":185},"Benchmark Concepts","/benchmarks/benchmark-concepts","7.benchmarks/0.benchmark-concepts","i-lucide-book-open",{"title":187,"path":188,"stem":189,"icon":126},"Benchmarking & Load Testing","/benchmarks/benchmarking-load-testing","7.benchmarks/1.benchmarking-load-testing",{"title":191,"path":192,"stem":193,"children":194,"icon":203},"Benchmark Results","/benchmarks/benchmark-results","7.benchmarks/2.benchmark-results",[195,199],{"title":196,"path":197,"stem":198,"icon":97},"Local Benchmark Comparison","/benchmarks/benchmark-results/local-benchmark-comparison","7.benchmarks/2.benchmark-results/1.local-benchmark-comparison",{"title":200,"path":201,"stem":202,"icon":26},"Redis + Hybrid Benchmark Comparison","/benchmarks/benchmark-results/redis-benchmark-comparison","7.benchmarks/2.benchmark-results/2.redis-benchmark-comparison","i-lucide-chart-no-axes-combined",{"title":205,"path":206,"stem":207,"children":208,"icon":210,"defaultOpen":65},"Changelog","/changelog","8.changelog/0.index",[209,211,216,220,224,228,232,236],{"title":205,"path":206,"stem":207,"icon":210},"i-lucide-scroll",{"title":212,"path":213,"stem":214,"icon":215},"v2.2.1","/changelog/v2-2-1","8.changelog/1.v2-2-1","i-lucide-tag",{"title":217,"path":218,"stem":219,"icon":215},"v2.2.0","/changelog/v2-2-0","8.changelog/2.v2-2-0",{"title":221,"path":222,"stem":223,"icon":215},"v2.1.0","/changelog/v2-1-0","8.changelog/3.v2-1-0",{"title":225,"path":226,"stem":227,"icon":215},"v2.0.0","/changelog/v2-0-0","8.changelog/4.v2-0-0",{"title":229,"path":230,"stem":231,"icon":215},"v1.1.0","/changelog/v1-1-0","8.changelog/5.v1-1-0",{"title":233,"path":234,"stem":235,"icon":215},"v1.0.1","/changelog/v1-0-1","8.changelog/6.v1-0-1",{"title":237,"path":238,"stem":239,"icon":215},"v1.0.0","/changelog/v1-0-0","8.changelog/7.v1-0-0",{"id":241,"title":128,"authors":242,"badge":242,"body":243,"date":242,"description":1926,"extension":1927,"links":242,"meta":1928,"navigation":1929,"path":129,"seo":1930,"stem":130,"__hash__":1931},"docs/5.actix-web/5.backends.md",null,{"type":244,"value":245,"toc":1920},"minimark",[246,321,325,329,540,546,548,551,907,914,917,922,1091,1098,1102,1113,1175,1903,1916],[247,248,249,268],"table",{},[250,251,252],"thead",{},[253,254,255,259,262,265],"tr",{},[256,257,258],"th",{},"Backend",[256,260,261],{},"Feature",[256,263,264],{},"Shared across instances",[256,266,267],{},"Cost per request",[269,270,271,288,305],"tbody",{},[253,272,273,279,282,285],{},[274,275,276],"td",{},[277,278,94],"code",{},[274,280,281],{},"none",[274,283,284],{},"No: each process counts on its own.",[274,286,287],{},"In memory.",[253,289,290,294,299,302],{},[274,291,292],{},[277,293,99],{},[274,295,296],{},[277,297,298],{},"redis",[274,300,301],{},"Yes, exactly.",[274,303,304],{},"One Redis round trip.",[253,306,307,311,315,318],{},[274,308,309],{},[277,310,103],{},[274,312,313],{},[277,314,298],{},[274,316,317],{},"Yes, eventually: counts sync every interval.",[274,319,320],{},"In memory for most requests.",[322,323,324],"p",{},"Each backend builds its Trypema provider and remembers the window, so the limit advertised in\nheaders always matches the one enforced. Build a backend once and clone it; clones share one\nprovider.",[326,327,94],"h2",{"id":328},"local",[330,331,336],"pre",{"className":332,"code":333,"language":334,"meta":335,"style":335},"language-rust shiki shiki-themes material-theme-lighter github-light github-dark monokai","use actix_trypema::Local;\nuse trypema::{BucketSize, RateLimiterBuilder, WindowSize};\n\nlet backend = Local::new(WindowSize::seconds_or_panic(60))?;\n\n// Any other provider option goes through Trypema's builder; the window is applied last.\nlet tuned = Local::configured(WindowSize::seconds_or_panic(60), |builder| {\n    builder.bucket_size(BucketSize::milliseconds_or_panic(50))\n})?;\n","rust","",[277,337,338,361,391,397,445,450,457,501,530],{"__ignoreMap":335},[339,340,343,347,351,355,357],"span",{"class":341,"line":342},"line",1,[339,344,346],{"class":345},"shWJe","use",[339,348,350],{"class":349},"sKvfc"," actix_trypema",[339,352,354],{"class":353},"sGXK2","::",[339,356,94],{"class":349},[339,358,360],{"class":359},"swvn1",";\n",[339,362,364,366,369,371,374,377,380,383,385,388],{"class":341,"line":363},2,[339,365,346],{"class":345},[339,367,368],{"class":349}," trypema",[339,370,354],{"class":353},[339,372,373],{"class":359},"{",[339,375,376],{"class":349},"BucketSize",[339,378,379],{"class":359},",",[339,381,382],{"class":349}," RateLimiterBuilder",[339,384,379],{"class":359},[339,386,387],{"class":349}," WindowSize",[339,389,390],{"class":359},"};\n",[339,392,394],{"class":341,"line":393},3,[339,395,396],{"emptyLinePlaceholder":33},"\n",[339,398,400,404,408,411,414,416,420,423,426,428,431,433,437,440,443],{"class":341,"line":399},4,[339,401,403],{"class":402},"srJo8","let",[339,405,407],{"class":406},"ss--_"," backend ",[339,409,410],{"class":353},"=",[339,412,413],{"class":349}," Local",[339,415,354],{"class":353},[339,417,419],{"class":418},"sD0ED","new",[339,421,422],{"class":359},"(",[339,424,425],{"class":349},"WindowSize",[339,427,354],{"class":353},[339,429,430],{"class":418},"seconds_or_panic",[339,432,422],{"class":359},[339,434,436],{"class":435},"sYThS","60",[339,438,439],{"class":359},"))",[339,441,442],{"class":353},"?",[339,444,360],{"class":359},[339,446,448],{"class":341,"line":447},5,[339,449,396],{"emptyLinePlaceholder":33},[339,451,453],{"class":341,"line":452},6,[339,454,456],{"class":455},"ss7Ak","// Any other provider option goes through Trypema's builder; the window is applied last.\n",[339,458,460,462,465,467,469,471,474,476,478,480,482,484,486,489,492,495,498],{"class":341,"line":459},7,[339,461,403],{"class":402},[339,463,464],{"class":406}," tuned ",[339,466,410],{"class":353},[339,468,413],{"class":349},[339,470,354],{"class":353},[339,472,473],{"class":418},"configured",[339,475,422],{"class":359},[339,477,425],{"class":349},[339,479,354],{"class":353},[339,481,430],{"class":418},[339,483,422],{"class":359},[339,485,436],{"class":435},[339,487,488],{"class":359},"),",[339,490,491],{"class":353}," |",[339,493,494],{"class":406},"builder",[339,496,497],{"class":353},"|",[339,499,500],{"class":359}," {\n",[339,502,504,507,510,513,515,517,519,522,524,527],{"class":341,"line":503},8,[339,505,506],{"class":406},"    builder",[339,508,509],{"class":353},".",[339,511,512],{"class":418},"bucket_size",[339,514,422],{"class":359},[339,516,376],{"class":349},[339,518,354],{"class":353},[339,520,521],{"class":418},"milliseconds_or_panic",[339,523,422],{"class":359},[339,525,526],{"class":435},"50",[339,528,529],{"class":359},"))\n",[339,531,533,536,538],{"class":341,"line":532},9,[339,534,535],{"class":359},"})",[339,537,442],{"class":353},[339,539,360],{"class":359},[322,541,542,543,545],{},"Use ",[277,544,94],{}," for a single instance, or for limits that are fine per instance.",[326,547,99],{"id":298},[322,549,550],{},"Every instance pointing at the same Redis and prefix shares one limit. Redis 7.2 or newer is\nrequired.",[330,552,554],{"className":332,"code":553,"language":334,"meta":335,"style":335},"use actix_trypema::{Redis, TrypemaLimiter, extract::PeerIp};\nuse trypema::{RateLimit, RateLimiterBuilder, WindowSize, redis::RedisKey};\n\nlet connection = redis::Client::open(\"redis://127.0.0.1:6379/\")?\n    .get_connection_manager()\n    .await?;\n\n// Services sharing one Redis keep their counts apart with their own prefix.\nlet prefix = RedisKey::try_from(\"checkout-api\")?;\nlet backend = Redis::configured(connection, WindowSize::minutes_or_panic(1), |builder| {\n    builder.prefix(prefix)\n})?;\n\nlet limiter = TrypemaLimiter::builder(backend)\n    .namespace(\"ip\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(60.0))\n    .build()?;\n",[277,555,556,585,618,622,661,672,684,688,693,725,770,787,796,801,824,843,863,892],{"__ignoreMap":335},[339,557,558,560,562,564,566,568,570,573,575,578,580,583],{"class":341,"line":342},[339,559,346],{"class":345},[339,561,350],{"class":349},[339,563,354],{"class":353},[339,565,373],{"class":359},[339,567,99],{"class":349},[339,569,379],{"class":359},[339,571,572],{"class":349}," TrypemaLimiter",[339,574,379],{"class":359},[339,576,577],{"class":349}," extract",[339,579,354],{"class":353},[339,581,582],{"class":349},"PeerIp",[339,584,390],{"class":359},[339,586,587,589,591,593,595,598,600,602,604,606,608,611,613,616],{"class":341,"line":363},[339,588,346],{"class":345},[339,590,368],{"class":349},[339,592,354],{"class":353},[339,594,373],{"class":359},[339,596,597],{"class":349},"RateLimit",[339,599,379],{"class":359},[339,601,382],{"class":349},[339,603,379],{"class":359},[339,605,387],{"class":349},[339,607,379],{"class":359},[339,609,610],{"class":349}," redis",[339,612,354],{"class":353},[339,614,615],{"class":349},"RedisKey",[339,617,390],{"class":359},[339,619,620],{"class":341,"line":393},[339,621,396],{"emptyLinePlaceholder":33},[339,623,624,626,629,631,633,635,638,640,643,645,649,653,655,658],{"class":341,"line":399},[339,625,403],{"class":402},[339,627,628],{"class":406}," connection ",[339,630,410],{"class":353},[339,632,610],{"class":349},[339,634,354],{"class":353},[339,636,637],{"class":349},"Client",[339,639,354],{"class":353},[339,641,642],{"class":418},"open",[339,644,422],{"class":359},[339,646,648],{"class":647},"siCPE","\"",[339,650,652],{"class":651},"sLACW","redis://127.0.0.1:6379/",[339,654,648],{"class":647},[339,656,657],{"class":359},")",[339,659,660],{"class":353},"?\n",[339,662,663,666,669],{"class":341,"line":447},[339,664,665],{"class":353},"    .",[339,667,668],{"class":418},"get_connection_manager",[339,670,671],{"class":359},"()\n",[339,673,674,676,680,682],{"class":341,"line":452},[339,675,665],{"class":353},[339,677,679],{"class":678},"sRxSC","await",[339,681,442],{"class":353},[339,683,360],{"class":359},[339,685,686],{"class":341,"line":459},[339,687,396],{"emptyLinePlaceholder":33},[339,689,690],{"class":341,"line":503},[339,691,692],{"class":455},"// Services sharing one Redis keep their counts apart with their own prefix.\n",[339,694,695,697,700,702,705,707,710,712,714,717,719,721,723],{"class":341,"line":532},[339,696,403],{"class":402},[339,698,699],{"class":406}," prefix ",[339,701,410],{"class":353},[339,703,704],{"class":349}," RedisKey",[339,706,354],{"class":353},[339,708,709],{"class":418},"try_from",[339,711,422],{"class":359},[339,713,648],{"class":647},[339,715,716],{"class":651},"checkout-api",[339,718,648],{"class":647},[339,720,657],{"class":359},[339,722,442],{"class":353},[339,724,360],{"class":359},[339,726,728,730,732,734,737,739,741,743,746,748,750,752,755,757,760,762,764,766,768],{"class":341,"line":727},10,[339,729,403],{"class":402},[339,731,407],{"class":406},[339,733,410],{"class":353},[339,735,736],{"class":349}," Redis",[339,738,354],{"class":353},[339,740,473],{"class":418},[339,742,422],{"class":359},[339,744,745],{"class":406},"connection",[339,747,379],{"class":359},[339,749,387],{"class":349},[339,751,354],{"class":353},[339,753,754],{"class":418},"minutes_or_panic",[339,756,422],{"class":359},[339,758,759],{"class":435},"1",[339,761,488],{"class":359},[339,763,491],{"class":353},[339,765,494],{"class":406},[339,767,497],{"class":353},[339,769,500],{"class":359},[339,771,773,775,777,780,782,784],{"class":341,"line":772},11,[339,774,506],{"class":406},[339,776,509],{"class":353},[339,778,779],{"class":418},"prefix",[339,781,422],{"class":359},[339,783,779],{"class":406},[339,785,786],{"class":359},")\n",[339,788,790,792,794],{"class":341,"line":789},12,[339,791,535],{"class":359},[339,793,442],{"class":353},[339,795,360],{"class":359},[339,797,799],{"class":341,"line":798},13,[339,800,396],{"emptyLinePlaceholder":33},[339,802,804,806,809,811,813,815,817,819,822],{"class":341,"line":803},14,[339,805,403],{"class":402},[339,807,808],{"class":406}," limiter ",[339,810,410],{"class":353},[339,812,572],{"class":349},[339,814,354],{"class":353},[339,816,494],{"class":418},[339,818,422],{"class":359},[339,820,821],{"class":406},"backend",[339,823,786],{"class":359},[339,825,827,829,832,834,836,839,841],{"class":341,"line":826},15,[339,828,665],{"class":353},[339,830,831],{"class":418},"namespace",[339,833,422],{"class":359},[339,835,648],{"class":647},[339,837,838],{"class":651},"ip",[339,840,648],{"class":647},[339,842,786],{"class":359},[339,844,846,848,851,853,855,857,860],{"class":341,"line":845},16,[339,847,665],{"class":353},[339,849,850],{"class":418},"extractor",[339,852,422],{"class":359},[339,854,582],{"class":349},[339,856,354],{"class":353},[339,858,859],{"class":418},"default",[339,861,862],{"class":359},"())\n",[339,864,866,868,871,873,875,877,880,882,884,887,890],{"class":341,"line":865},17,[339,867,665],{"class":353},[339,869,870],{"class":418},"rate",[339,872,422],{"class":359},[339,874,597],{"class":349},[339,876,354],{"class":353},[339,878,879],{"class":418},"per_minute_or_panic",[339,881,422],{"class":359},[339,883,436],{"class":435},[339,885,509],{"class":886},"sMTiH",[339,888,889],{"class":435},"0",[339,891,529],{"class":359},[339,893,895,897,900,903,905],{"class":341,"line":894},18,[339,896,665],{"class":353},[339,898,899],{"class":418},"build",[339,901,902],{"class":359},"()",[339,904,442],{"class":353},[339,906,360],{"class":359},[322,908,909,910,913],{},"The prefix separates services or environments sharing one Redis; the namespace separates\nlimiters inside one service. ",[277,911,912],{},"Redis::new(connection, window)"," uses the default prefix.",[326,915,103],{"id":916},"hybrid",[322,918,919,921],{},[277,920,103],{}," decides most requests from in-process state and syncs counts to Redis in the\nbackground. It shares limits across instances at close to local speed. The trade-off: an\ninstance's view of the other instances lags by up to one sync interval, so the combined limit\ncan briefly overshoot.",[330,923,925],{"className":332,"code":924,"language":334,"meta":335,"style":335},"use actix_trypema::Hybrid;\nuse trypema::{WindowSize, hybrid::SyncInterval};\n\nlet connection = redis::Client::open(\"redis://127.0.0.1:6379/\")?\n    .get_connection_manager()\n    .await?;\n\nlet backend = Hybrid::configured(connection, WindowSize::minutes_or_panic(1), |builder| {\n    builder.sync_interval(SyncInterval::milliseconds_or_panic(50))\n})?;\n",[277,926,927,939,963,967,997,1005,1015,1019,1060,1083],{"__ignoreMap":335},[339,928,929,931,933,935,937],{"class":341,"line":342},[339,930,346],{"class":345},[339,932,350],{"class":349},[339,934,354],{"class":353},[339,936,103],{"class":349},[339,938,360],{"class":359},[339,940,941,943,945,947,949,951,953,956,958,961],{"class":341,"line":363},[339,942,346],{"class":345},[339,944,368],{"class":349},[339,946,354],{"class":353},[339,948,373],{"class":359},[339,950,425],{"class":349},[339,952,379],{"class":359},[339,954,955],{"class":349}," hybrid",[339,957,354],{"class":353},[339,959,960],{"class":349},"SyncInterval",[339,962,390],{"class":359},[339,964,965],{"class":341,"line":393},[339,966,396],{"emptyLinePlaceholder":33},[339,968,969,971,973,975,977,979,981,983,985,987,989,991,993,995],{"class":341,"line":399},[339,970,403],{"class":402},[339,972,628],{"class":406},[339,974,410],{"class":353},[339,976,610],{"class":349},[339,978,354],{"class":353},[339,980,637],{"class":349},[339,982,354],{"class":353},[339,984,642],{"class":418},[339,986,422],{"class":359},[339,988,648],{"class":647},[339,990,652],{"class":651},[339,992,648],{"class":647},[339,994,657],{"class":359},[339,996,660],{"class":353},[339,998,999,1001,1003],{"class":341,"line":447},[339,1000,665],{"class":353},[339,1002,668],{"class":418},[339,1004,671],{"class":359},[339,1006,1007,1009,1011,1013],{"class":341,"line":452},[339,1008,665],{"class":353},[339,1010,679],{"class":678},[339,1012,442],{"class":353},[339,1014,360],{"class":359},[339,1016,1017],{"class":341,"line":459},[339,1018,396],{"emptyLinePlaceholder":33},[339,1020,1021,1023,1025,1027,1030,1032,1034,1036,1038,1040,1042,1044,1046,1048,1050,1052,1054,1056,1058],{"class":341,"line":503},[339,1022,403],{"class":402},[339,1024,407],{"class":406},[339,1026,410],{"class":353},[339,1028,1029],{"class":349}," Hybrid",[339,1031,354],{"class":353},[339,1033,473],{"class":418},[339,1035,422],{"class":359},[339,1037,745],{"class":406},[339,1039,379],{"class":359},[339,1041,387],{"class":349},[339,1043,354],{"class":353},[339,1045,754],{"class":418},[339,1047,422],{"class":359},[339,1049,759],{"class":435},[339,1051,488],{"class":359},[339,1053,491],{"class":353},[339,1055,494],{"class":406},[339,1057,497],{"class":353},[339,1059,500],{"class":359},[339,1061,1062,1064,1066,1069,1071,1073,1075,1077,1079,1081],{"class":341,"line":532},[339,1063,506],{"class":406},[339,1065,509],{"class":353},[339,1067,1068],{"class":418},"sync_interval",[339,1070,422],{"class":359},[339,1072,960],{"class":349},[339,1074,354],{"class":353},[339,1076,521],{"class":418},[339,1078,422],{"class":359},[339,1080,526],{"class":435},[339,1082,529],{"class":359},[339,1084,1085,1087,1089],{"class":341,"line":727},[339,1086,535],{"class":359},[339,1088,442],{"class":353},[339,1090,360],{"class":359},[322,1092,1093,1094,1097],{},"Most hybrid requests are decided without awaiting anything. Only requests that need Redis (a\nkey's first request, a refresh, or a key whose local share ran out) take the async path.\n",[277,1095,1096],{},"remaining_header(true)"," sends every request down the async path, so leave it off where speed\nmatters.",[326,1099,1101],{"id":1100},"when-redis-fails","When Redis fails",[322,1103,1104,1105,1108,1109,1112],{},"Every Redis and hybrid call is bounded by ",[277,1106,1107],{},"backend_timeout"," (200 ms by default). A timeout or an\nerror is a backend failure, handled by ",[277,1110,1111],{},"on_backend_error",":",[247,1114,1115,1125],{},[250,1116,1117],{},[253,1118,1119,1122],{},[256,1120,1121],{},"Policy",[256,1123,1124],{},"On failure",[269,1126,1127,1138,1152,1165],{},[253,1128,1129,1135],{},[274,1130,1131,1134],{},[277,1132,1133],{},"BackendErrorPolicy::FailOpen"," (default)",[274,1136,1137],{},"Admit the request. A limiter outage should not become an API outage.",[253,1139,1140,1145],{},[274,1141,1142],{},[277,1143,1144],{},"BackendErrorPolicy::FailClosed",[274,1146,1147,1148,1151],{},"Reject with ",[277,1149,1150],{},"503 Service Unavailable",". Use it on login, OTP and other abuse-prone routes.",[253,1153,1154,1159],{},[274,1155,1156],{},[277,1157,1158],{},"BackendErrorPolicy::Fallback(local)",[274,1160,1161,1162,1164],{},"Decide with a ",[277,1163,94],{}," backend instead; each instance enforces the limit on its own.",[253,1166,1167,1172],{},[274,1168,1169],{},[277,1170,1171],{},"BackendErrorPolicy::Custom(fn)",[274,1173,1174],{},"Decide per failure.",[330,1176,1178],{"className":332,"code":1177,"language":334,"meta":335,"style":335},"use std::{sync::Arc, time::Duration};\n\nuse actix_trypema::{\n    BackendErrorPolicy, BackendFailure, ErrorAction, Local, Redis, TrypemaLimiter,\n    extract::PeerIp,\n};\nuse actix_web::http::StatusCode;\nuse trypema::{RateLimit, WindowSize};\n\nlet window = WindowSize::minutes_or_panic(1);\n\n// Login: never let attempts through unchecked.\nlet login = TrypemaLimiter::builder(Redis::new(connection.clone(), window)?)\n    .namespace(\"login\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(5.0))\n    .on_backend_error(BackendErrorPolicy::FailClosed)\n    .backend_timeout(Duration::from_millis(30))\n    .build()?;\n\n// API: keep limiting per instance while Redis is down. The fallback must use the same window.\nlet api = TrypemaLimiter::builder(Redis::new(connection.clone(), window)?)\n    .namespace(\"api\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(600.0))\n    .on_backend_error(BackendErrorPolicy::Fallback(Local::new(window)?))\n    .build()?;\n\n// Search: admit on errors, but shed load when Redis is merely slow.\nlet search = TrypemaLimiter::builder(Redis::new(connection, window)?)\n    .namespace(\"search\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(120.0))\n    .on_backend_error(BackendErrorPolicy::Custom(Arc::new(|failure| match failure {\n        BackendFailure::Timeout(_) => ErrorAction::Reject {\n            status: StatusCode::SERVICE_UNAVAILABLE,\n        },\n        _ => ErrorAction::Admit,\n    })))\n    .build()?;\n",[277,1179,1180,1211,1215,1226,1256,1267,1271,1290,1308,1312,1334,1338,1343,1387,1404,1420,1445,1463,1485,1498,1503,1509,1551,1569,1586,1612,1647,1660,1665,1671,1709,1727,1744,1770,1811,1841,1860,1866,1884,1890],{"__ignoreMap":335},[339,1181,1182,1184,1187,1189,1191,1194,1196,1199,1201,1204,1206,1209],{"class":341,"line":342},[339,1183,346],{"class":345},[339,1185,1186],{"class":349}," std",[339,1188,354],{"class":353},[339,1190,373],{"class":359},[339,1192,1193],{"class":349},"sync",[339,1195,354],{"class":353},[339,1197,1198],{"class":349},"Arc",[339,1200,379],{"class":359},[339,1202,1203],{"class":349}," time",[339,1205,354],{"class":353},[339,1207,1208],{"class":349},"Duration",[339,1210,390],{"class":359},[339,1212,1213],{"class":341,"line":363},[339,1214,396],{"emptyLinePlaceholder":33},[339,1216,1217,1219,1221,1223],{"class":341,"line":393},[339,1218,346],{"class":345},[339,1220,350],{"class":349},[339,1222,354],{"class":353},[339,1224,1225],{"class":359},"{\n",[339,1227,1228,1231,1233,1236,1238,1241,1243,1245,1247,1249,1251,1253],{"class":341,"line":399},[339,1229,1230],{"class":349},"    BackendErrorPolicy",[339,1232,379],{"class":359},[339,1234,1235],{"class":349}," BackendFailure",[339,1237,379],{"class":359},[339,1239,1240],{"class":349}," ErrorAction",[339,1242,379],{"class":359},[339,1244,413],{"class":349},[339,1246,379],{"class":359},[339,1248,736],{"class":349},[339,1250,379],{"class":359},[339,1252,572],{"class":349},[339,1254,1255],{"class":359},",\n",[339,1257,1258,1261,1263,1265],{"class":341,"line":447},[339,1259,1260],{"class":349},"    extract",[339,1262,354],{"class":353},[339,1264,582],{"class":349},[339,1266,1255],{"class":359},[339,1268,1269],{"class":341,"line":452},[339,1270,390],{"class":359},[339,1272,1273,1275,1278,1280,1283,1285,1288],{"class":341,"line":459},[339,1274,346],{"class":345},[339,1276,1277],{"class":349}," actix_web",[339,1279,354],{"class":353},[339,1281,1282],{"class":349},"http",[339,1284,354],{"class":353},[339,1286,1287],{"class":349},"StatusCode",[339,1289,360],{"class":359},[339,1291,1292,1294,1296,1298,1300,1302,1304,1306],{"class":341,"line":503},[339,1293,346],{"class":345},[339,1295,368],{"class":349},[339,1297,354],{"class":353},[339,1299,373],{"class":359},[339,1301,597],{"class":349},[339,1303,379],{"class":359},[339,1305,387],{"class":349},[339,1307,390],{"class":359},[339,1309,1310],{"class":341,"line":532},[339,1311,396],{"emptyLinePlaceholder":33},[339,1313,1314,1316,1319,1321,1323,1325,1327,1329,1331],{"class":341,"line":727},[339,1315,403],{"class":402},[339,1317,1318],{"class":406}," window ",[339,1320,410],{"class":353},[339,1322,387],{"class":349},[339,1324,354],{"class":353},[339,1326,754],{"class":418},[339,1328,422],{"class":359},[339,1330,759],{"class":435},[339,1332,1333],{"class":359},");\n",[339,1335,1336],{"class":341,"line":772},[339,1337,396],{"emptyLinePlaceholder":33},[339,1339,1340],{"class":341,"line":789},[339,1341,1342],{"class":455},"// Login: never let attempts through unchecked.\n",[339,1344,1345,1347,1350,1352,1354,1356,1358,1360,1362,1364,1366,1368,1370,1372,1375,1378,1381,1383,1385],{"class":341,"line":798},[339,1346,403],{"class":402},[339,1348,1349],{"class":406}," login ",[339,1351,410],{"class":353},[339,1353,572],{"class":349},[339,1355,354],{"class":353},[339,1357,494],{"class":418},[339,1359,422],{"class":359},[339,1361,99],{"class":349},[339,1363,354],{"class":353},[339,1365,419],{"class":418},[339,1367,422],{"class":359},[339,1369,745],{"class":406},[339,1371,509],{"class":353},[339,1373,1374],{"class":418},"clone",[339,1376,1377],{"class":359},"(),",[339,1379,1380],{"class":406}," window",[339,1382,657],{"class":359},[339,1384,442],{"class":353},[339,1386,786],{"class":359},[339,1388,1389,1391,1393,1395,1397,1400,1402],{"class":341,"line":803},[339,1390,665],{"class":353},[339,1392,831],{"class":418},[339,1394,422],{"class":359},[339,1396,648],{"class":647},[339,1398,1399],{"class":651},"login",[339,1401,648],{"class":647},[339,1403,786],{"class":359},[339,1405,1406,1408,1410,1412,1414,1416,1418],{"class":341,"line":826},[339,1407,665],{"class":353},[339,1409,850],{"class":418},[339,1411,422],{"class":359},[339,1413,582],{"class":349},[339,1415,354],{"class":353},[339,1417,859],{"class":418},[339,1419,862],{"class":359},[339,1421,1422,1424,1426,1428,1430,1432,1434,1436,1439,1441,1443],{"class":341,"line":845},[339,1423,665],{"class":353},[339,1425,870],{"class":418},[339,1427,422],{"class":359},[339,1429,597],{"class":349},[339,1431,354],{"class":353},[339,1433,879],{"class":418},[339,1435,422],{"class":359},[339,1437,1438],{"class":435},"5",[339,1440,509],{"class":886},[339,1442,889],{"class":435},[339,1444,529],{"class":359},[339,1446,1447,1449,1451,1453,1456,1458,1461],{"class":341,"line":865},[339,1448,665],{"class":353},[339,1450,1111],{"class":418},[339,1452,422],{"class":359},[339,1454,1455],{"class":349},"BackendErrorPolicy",[339,1457,354],{"class":353},[339,1459,1460],{"class":349},"FailClosed",[339,1462,786],{"class":359},[339,1464,1465,1467,1469,1471,1473,1475,1478,1480,1483],{"class":341,"line":894},[339,1466,665],{"class":353},[339,1468,1107],{"class":418},[339,1470,422],{"class":359},[339,1472,1208],{"class":349},[339,1474,354],{"class":353},[339,1476,1477],{"class":418},"from_millis",[339,1479,422],{"class":359},[339,1481,1482],{"class":435},"30",[339,1484,529],{"class":359},[339,1486,1488,1490,1492,1494,1496],{"class":341,"line":1487},19,[339,1489,665],{"class":353},[339,1491,899],{"class":418},[339,1493,902],{"class":359},[339,1495,442],{"class":353},[339,1497,360],{"class":359},[339,1499,1501],{"class":341,"line":1500},20,[339,1502,396],{"emptyLinePlaceholder":33},[339,1504,1506],{"class":341,"line":1505},21,[339,1507,1508],{"class":455},"// API: keep limiting per instance while Redis is down. The fallback must use the same window.\n",[339,1510,1512,1514,1517,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537,1539,1541,1543,1545,1547,1549],{"class":341,"line":1511},22,[339,1513,403],{"class":402},[339,1515,1516],{"class":406}," api ",[339,1518,410],{"class":353},[339,1520,572],{"class":349},[339,1522,354],{"class":353},[339,1524,494],{"class":418},[339,1526,422],{"class":359},[339,1528,99],{"class":349},[339,1530,354],{"class":353},[339,1532,419],{"class":418},[339,1534,422],{"class":359},[339,1536,745],{"class":406},[339,1538,509],{"class":353},[339,1540,1374],{"class":418},[339,1542,1377],{"class":359},[339,1544,1380],{"class":406},[339,1546,657],{"class":359},[339,1548,442],{"class":353},[339,1550,786],{"class":359},[339,1552,1554,1556,1558,1560,1562,1565,1567],{"class":341,"line":1553},23,[339,1555,665],{"class":353},[339,1557,831],{"class":418},[339,1559,422],{"class":359},[339,1561,648],{"class":647},[339,1563,1564],{"class":651},"api",[339,1566,648],{"class":647},[339,1568,786],{"class":359},[339,1570,1572,1574,1576,1578,1580,1582,1584],{"class":341,"line":1571},24,[339,1573,665],{"class":353},[339,1575,850],{"class":418},[339,1577,422],{"class":359},[339,1579,582],{"class":349},[339,1581,354],{"class":353},[339,1583,859],{"class":418},[339,1585,862],{"class":359},[339,1587,1589,1591,1593,1595,1597,1599,1601,1603,1606,1608,1610],{"class":341,"line":1588},25,[339,1590,665],{"class":353},[339,1592,870],{"class":418},[339,1594,422],{"class":359},[339,1596,597],{"class":349},[339,1598,354],{"class":353},[339,1600,879],{"class":418},[339,1602,422],{"class":359},[339,1604,1605],{"class":435},"600",[339,1607,509],{"class":886},[339,1609,889],{"class":435},[339,1611,529],{"class":359},[339,1613,1615,1617,1619,1621,1623,1625,1628,1630,1632,1634,1636,1638,1641,1643,1645],{"class":341,"line":1614},26,[339,1616,665],{"class":353},[339,1618,1111],{"class":418},[339,1620,422],{"class":359},[339,1622,1455],{"class":349},[339,1624,354],{"class":353},[339,1626,1627],{"class":418},"Fallback",[339,1629,422],{"class":359},[339,1631,94],{"class":349},[339,1633,354],{"class":353},[339,1635,419],{"class":418},[339,1637,422],{"class":359},[339,1639,1640],{"class":406},"window",[339,1642,657],{"class":359},[339,1644,442],{"class":353},[339,1646,529],{"class":359},[339,1648,1650,1652,1654,1656,1658],{"class":341,"line":1649},27,[339,1651,665],{"class":353},[339,1653,899],{"class":418},[339,1655,902],{"class":359},[339,1657,442],{"class":353},[339,1659,360],{"class":359},[339,1661,1663],{"class":341,"line":1662},28,[339,1664,396],{"emptyLinePlaceholder":33},[339,1666,1668],{"class":341,"line":1667},29,[339,1669,1670],{"class":455},"// Search: admit on errors, but shed load when Redis is merely slow.\n",[339,1672,1674,1676,1679,1681,1683,1685,1687,1689,1691,1693,1695,1697,1699,1701,1703,1705,1707],{"class":341,"line":1673},30,[339,1675,403],{"class":402},[339,1677,1678],{"class":406}," search ",[339,1680,410],{"class":353},[339,1682,572],{"class":349},[339,1684,354],{"class":353},[339,1686,494],{"class":418},[339,1688,422],{"class":359},[339,1690,99],{"class":349},[339,1692,354],{"class":353},[339,1694,419],{"class":418},[339,1696,422],{"class":359},[339,1698,745],{"class":406},[339,1700,379],{"class":359},[339,1702,1380],{"class":406},[339,1704,657],{"class":359},[339,1706,442],{"class":353},[339,1708,786],{"class":359},[339,1710,1712,1714,1716,1718,1720,1723,1725],{"class":341,"line":1711},31,[339,1713,665],{"class":353},[339,1715,831],{"class":418},[339,1717,422],{"class":359},[339,1719,648],{"class":647},[339,1721,1722],{"class":651},"search",[339,1724,648],{"class":647},[339,1726,786],{"class":359},[339,1728,1730,1732,1734,1736,1738,1740,1742],{"class":341,"line":1729},32,[339,1731,665],{"class":353},[339,1733,850],{"class":418},[339,1735,422],{"class":359},[339,1737,582],{"class":349},[339,1739,354],{"class":353},[339,1741,859],{"class":418},[339,1743,862],{"class":359},[339,1745,1747,1749,1751,1753,1755,1757,1759,1761,1764,1766,1768],{"class":341,"line":1746},33,[339,1748,665],{"class":353},[339,1750,870],{"class":418},[339,1752,422],{"class":359},[339,1754,597],{"class":349},[339,1756,354],{"class":353},[339,1758,879],{"class":418},[339,1760,422],{"class":359},[339,1762,1763],{"class":435},"120",[339,1765,509],{"class":886},[339,1767,889],{"class":435},[339,1769,529],{"class":359},[339,1771,1773,1775,1777,1779,1781,1783,1786,1788,1790,1792,1794,1796,1798,1801,1803,1806,1809],{"class":341,"line":1772},34,[339,1774,665],{"class":353},[339,1776,1111],{"class":418},[339,1778,422],{"class":359},[339,1780,1455],{"class":349},[339,1782,354],{"class":353},[339,1784,1785],{"class":418},"Custom",[339,1787,422],{"class":359},[339,1789,1198],{"class":349},[339,1791,354],{"class":353},[339,1793,419],{"class":418},[339,1795,422],{"class":359},[339,1797,497],{"class":353},[339,1799,1800],{"class":406},"failure",[339,1802,497],{"class":353},[339,1804,1805],{"class":678}," match",[339,1807,1808],{"class":406}," failure ",[339,1810,1225],{"class":359},[339,1812,1814,1817,1819,1822,1824,1827,1829,1832,1834,1836,1839],{"class":341,"line":1813},35,[339,1815,1816],{"class":349},"        BackendFailure",[339,1818,354],{"class":353},[339,1820,1821],{"class":418},"Timeout",[339,1823,422],{"class":359},[339,1825,1826],{"class":406},"_",[339,1828,657],{"class":359},[339,1830,1831],{"class":353}," =>",[339,1833,1240],{"class":349},[339,1835,354],{"class":353},[339,1837,1838],{"class":349},"Reject",[339,1840,500],{"class":359},[339,1842,1844,1847,1849,1852,1854,1858],{"class":341,"line":1843},36,[339,1845,1846],{"class":406},"            status",[339,1848,1112],{"class":353},[339,1850,1851],{"class":349}," StatusCode",[339,1853,354],{"class":353},[339,1855,1857],{"class":1856},"sQeA1","SERVICE_UNAVAILABLE",[339,1859,1255],{"class":359},[339,1861,1863],{"class":341,"line":1862},37,[339,1864,1865],{"class":359},"        },\n",[339,1867,1869,1872,1875,1877,1879,1882],{"class":341,"line":1868},38,[339,1870,1871],{"class":406},"        _ ",[339,1873,1874],{"class":353},"=>",[339,1876,1240],{"class":349},[339,1878,354],{"class":353},[339,1880,1881],{"class":349},"Admit",[339,1883,1255],{"class":359},[339,1885,1887],{"class":341,"line":1886},39,[339,1888,1889],{"class":359},"    })))\n",[339,1891,1893,1895,1897,1899,1901],{"class":341,"line":1892},40,[339,1894,665],{"class":353},[339,1896,899],{"class":418},[339,1898,902],{"class":359},[339,1900,442],{"class":353},[339,1902,360],{"class":359},[322,1904,1905,1906,1908,1909,1912,1913,1915],{},"With ",[277,1907,1627],{},", ",[277,1910,1911],{},"n"," instances admit up to ",[277,1914,1911],{}," times the limit while Redis is down, and those\ncounts are not carried back when it recovers. Failures are logged as warnings at most once per\nsecond per process, with the namespace and the failure kind only.",[1917,1918,1919],"style",{},"html pre.shiki code .shWJe, html code.shiki .shWJe{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sKvfc, html code.shiki .sKvfc{--shiki-light:#E2931D;--shiki-light-text-decoration:inherit;--shiki-default:#6F42C1;--shiki-default-text-decoration:inherit;--shiki-dark:#B392F0;--shiki-dark-text-decoration:inherit;--shiki-sepia:#A6E22E;--shiki-sepia-text-decoration:underline}html pre.shiki code .sGXK2, html code.shiki .sGXK2{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .swvn1, html code.shiki .swvn1{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .srJo8, html code.shiki .srJo8{--shiki-light:#9C3EDA;--shiki-light-font-style:inherit;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .ss--_, html code.shiki .ss--_{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sD0ED, html code.shiki .sD0ED{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sYThS, html code.shiki .sYThS{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .ss7Ak, html code.shiki .ss7Ak{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit;--shiki-sepia:#88846F;--shiki-sepia-font-style:inherit}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 .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .siCPE, html code.shiki .siCPE{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sLACW, html code.shiki .sLACW{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sRxSC, html code.shiki .sRxSC{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#F92672;--shiki-sepia-font-style:inherit}html pre.shiki code .sMTiH, html code.shiki .sMTiH{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sQeA1, html code.shiki .sQeA1{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}",{"title":335,"searchDepth":342,"depth":363,"links":1921},[1922,1923,1924,1925],{"id":328,"depth":363,"text":94},{"id":298,"depth":363,"text":99},{"id":916,"depth":363,"text":103},{"id":1100,"depth":363,"text":1101},"Choose where counts live (in process, in Redis, or both), tune the provider, and decide what happens when Redis fails.","md",{},{"icon":26},{"title":128,"description":1926},"7VNYkiDI9DVtCLqEI6hTB8HsPrkE6OISClXyZtiarXM",[1933,1935],{"title":123,"path":124,"stem":125,"description":1934,"icon":126,"children":-1},"Set rates and windows, give plans different limits, charge expensive requests more, shed load gradually, and stack several limiters.",{"title":132,"path":133,"stem":134,"description":1936,"icon":135,"children":-1},"The headers admitted and rejected responses carry, and how to customize the rejection body and status.",1791663192240]