[{"data":1,"prerenderedAt":2494},["ShallowReactive",2],{"navigation":3,"/actix-web/limits":240,"/actix-web/limits-surround":2489},[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":123,"authors":242,"badge":242,"body":243,"date":242,"description":2483,"extension":2484,"links":242,"meta":2485,"navigation":2486,"path":124,"seo":2487,"stem":125,"__hash__":2488},"docs/5.actix-web/4.limits.md",null,{"type":244,"value":245,"toc":2475},"minimark",[246,251,255,490,541,556,560,566,955,971,979,983,990,1239,1250,1253,1264,1500,1509,1513,1519,1795,1799,1802,2460,2471],[247,248,250],"h2",{"id":249},"rate-and-window","Rate and window",[252,253,254],"p",{},"The backend fixes the window; the limiter sets the rate. The capacity per window is the rate\ntimes the window, rounded down:",[256,257,262],"pre",{"className":258,"code":259,"language":260,"meta":261,"style":261},"language-rust shiki shiki-themes material-theme-lighter github-light github-dark monokai","use actix_trypema::{Local, TrypemaLimiter, extract::PeerIp};\nuse trypema::{RateLimit, WindowSize};\n\n// 10 requests per second over a 60-second sliding window: 600 per window.\nlet limiter = TrypemaLimiter::builder(Local::new(WindowSize::seconds_or_panic(60))?)\n    .namespace(\"ip\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_second_or_panic(10.0))\n    .build()?;\n","rust","",[263,264,265,307,329,335,342,399,422,442,474],"code",{"__ignoreMap":261},[266,267,270,274,278,282,286,288,291,294,296,299,301,304],"span",{"class":268,"line":269},"line",1,[266,271,273],{"class":272},"shWJe","use",[266,275,277],{"class":276},"sKvfc"," actix_trypema",[266,279,281],{"class":280},"sGXK2","::",[266,283,285],{"class":284},"swvn1","{",[266,287,94],{"class":276},[266,289,290],{"class":284},",",[266,292,293],{"class":276}," TrypemaLimiter",[266,295,290],{"class":284},[266,297,298],{"class":276}," extract",[266,300,281],{"class":280},[266,302,303],{"class":276},"PeerIp",[266,305,306],{"class":284},"};\n",[266,308,310,312,315,317,319,322,324,327],{"class":268,"line":309},2,[266,311,273],{"class":272},[266,313,314],{"class":276}," trypema",[266,316,281],{"class":280},[266,318,285],{"class":284},[266,320,321],{"class":276},"RateLimit",[266,323,290],{"class":284},[266,325,326],{"class":276}," WindowSize",[266,328,306],{"class":284},[266,330,332],{"class":268,"line":331},3,[266,333,334],{"emptyLinePlaceholder":33},"\n",[266,336,338],{"class":268,"line":337},4,[266,339,341],{"class":340},"ss7Ak","// 10 requests per second over a 60-second sliding window: 600 per window.\n",[266,343,345,349,353,356,358,360,364,367,369,371,374,376,379,381,384,386,390,393,396],{"class":268,"line":344},5,[266,346,348],{"class":347},"srJo8","let",[266,350,352],{"class":351},"ss--_"," limiter ",[266,354,355],{"class":280},"=",[266,357,293],{"class":276},[266,359,281],{"class":280},[266,361,363],{"class":362},"sD0ED","builder",[266,365,366],{"class":284},"(",[266,368,94],{"class":276},[266,370,281],{"class":280},[266,372,373],{"class":362},"new",[266,375,366],{"class":284},[266,377,378],{"class":276},"WindowSize",[266,380,281],{"class":280},[266,382,383],{"class":362},"seconds_or_panic",[266,385,366],{"class":284},[266,387,389],{"class":388},"sYThS","60",[266,391,392],{"class":284},"))",[266,394,395],{"class":280},"?",[266,397,398],{"class":284},")\n",[266,400,402,405,408,410,414,418,420],{"class":268,"line":401},6,[266,403,404],{"class":280},"    .",[266,406,407],{"class":362},"namespace",[266,409,366],{"class":284},[266,411,413],{"class":412},"siCPE","\"",[266,415,417],{"class":416},"sLACW","ip",[266,419,413],{"class":412},[266,421,398],{"class":284},[266,423,425,427,430,432,434,436,439],{"class":268,"line":424},7,[266,426,404],{"class":280},[266,428,429],{"class":362},"extractor",[266,431,366],{"class":284},[266,433,303],{"class":276},[266,435,281],{"class":280},[266,437,438],{"class":362},"default",[266,440,441],{"class":284},"())\n",[266,443,445,447,450,452,454,456,459,461,464,468,471],{"class":268,"line":444},8,[266,446,404],{"class":280},[266,448,449],{"class":362},"rate",[266,451,366],{"class":284},[266,453,321],{"class":276},[266,455,281],{"class":280},[266,457,458],{"class":362},"per_second_or_panic",[266,460,366],{"class":284},[266,462,463],{"class":388},"10",[266,465,467],{"class":466},"sMTiH",".",[266,469,470],{"class":388},"0",[266,472,473],{"class":284},"))\n",[266,475,477,479,482,485,487],{"class":268,"line":476},9,[266,478,404],{"class":280},[266,480,481],{"class":362},"build",[266,483,484],{"class":284},"()",[266,486,395],{"class":280},[266,488,489],{"class":284},";\n",[252,491,492,494,495,498,499,498,502,498,505,498,508,511,512,515,516,494,518,498,521,498,524,498,527,498,530,511,533,536,537,540],{},[263,493,321],{}," has ",[263,496,497],{},"per_second",", ",[263,500,501],{},"per_minute",[263,503,504],{},"per_hour",[263,506,507],{},"per_day",[263,509,510],{},"per_week"," and ",[263,513,514],{},"per_month","\nconstructors; ",[263,517,378],{},[263,519,520],{},"seconds",[263,522,523],{},"minutes",[263,525,526],{},"hours",[263,528,529],{},"days",[263,531,532],{},"weeks",[263,534,535],{},"months",". Each\nhas an ",[263,538,539],{},"_or_panic"," twin. The window is sliding: a request counts until a full window has passed\nsince it was made, so there is no burst at window boundaries.",[252,542,543,544,547,548,551,552,555],{},"A rate whose capacity rounds down to zero is rejected by ",[263,545,546],{},"build()"," with\n",[263,549,550],{},"ConfigError::ZeroCapacity",": ",[263,553,554],{},"RateLimit::per_hour(30.0)"," on a 60-second window admits 0.5\nrequests per window.",[247,557,559],{"id":558},"plan-tiers","Plan tiers",[252,561,562,565],{},[263,563,564],{},"rate_fn"," picks the rate per request, from the request and the extracted key:",[256,567,569],{"className":258,"code":568,"language":260,"meta":261,"style":261},"use actix_trypema::{KeyError, Local, TrypemaLimiter};\nuse trypema::{RateLimit, WindowSize};\n\nlet limiter = TrypemaLimiter::builder(Local::new(WindowSize::seconds_or_panic(60))?)\n    .namespace(\"apikey\")\n    // Your validation puts the plan in the key, for example \"pro:account-2\".\n    .extractor_fn(|req| {\n        req.headers()\n            .get(\"x-plan-key\")\n            .and_then(|value| value.to_str().ok())\n            .map(str::to_string)\n            .ok_or(KeyError::InvalidValue { reason: \"missing plan key\" })\n    })\n    .rate_fn(|_req, key| {\n        if key.starts_with(\"pro:\") {\n            RateLimit::per_minute_or_panic(1_000.0)\n        } else {\n            RateLimit::per_minute_or_panic(60.0)\n        }\n    })\n    .build()?;\n",[263,570,571,595,613,617,657,674,679,699,712,731,765,785,822,828,851,879,901,912,931,937,942],{"__ignoreMap":261},[266,572,573,575,577,579,581,584,586,589,591,593],{"class":268,"line":269},[266,574,273],{"class":272},[266,576,277],{"class":276},[266,578,281],{"class":280},[266,580,285],{"class":284},[266,582,583],{"class":276},"KeyError",[266,585,290],{"class":284},[266,587,588],{"class":276}," Local",[266,590,290],{"class":284},[266,592,293],{"class":276},[266,594,306],{"class":284},[266,596,597,599,601,603,605,607,609,611],{"class":268,"line":309},[266,598,273],{"class":272},[266,600,314],{"class":276},[266,602,281],{"class":280},[266,604,285],{"class":284},[266,606,321],{"class":276},[266,608,290],{"class":284},[266,610,326],{"class":276},[266,612,306],{"class":284},[266,614,615],{"class":268,"line":331},[266,616,334],{"emptyLinePlaceholder":33},[266,618,619,621,623,625,627,629,631,633,635,637,639,641,643,645,647,649,651,653,655],{"class":268,"line":337},[266,620,348],{"class":347},[266,622,352],{"class":351},[266,624,355],{"class":280},[266,626,293],{"class":276},[266,628,281],{"class":280},[266,630,363],{"class":362},[266,632,366],{"class":284},[266,634,94],{"class":276},[266,636,281],{"class":280},[266,638,373],{"class":362},[266,640,366],{"class":284},[266,642,378],{"class":276},[266,644,281],{"class":280},[266,646,383],{"class":362},[266,648,366],{"class":284},[266,650,389],{"class":388},[266,652,392],{"class":284},[266,654,395],{"class":280},[266,656,398],{"class":284},[266,658,659,661,663,665,667,670,672],{"class":268,"line":344},[266,660,404],{"class":280},[266,662,407],{"class":362},[266,664,366],{"class":284},[266,666,413],{"class":412},[266,668,669],{"class":416},"apikey",[266,671,413],{"class":412},[266,673,398],{"class":284},[266,675,676],{"class":268,"line":401},[266,677,678],{"class":340},"    // Your validation puts the plan in the key, for example \"pro:account-2\".\n",[266,680,681,683,686,688,691,694,696],{"class":268,"line":424},[266,682,404],{"class":280},[266,684,685],{"class":362},"extractor_fn",[266,687,366],{"class":284},[266,689,690],{"class":280},"|",[266,692,693],{"class":351},"req",[266,695,690],{"class":280},[266,697,698],{"class":284}," {\n",[266,700,701,704,706,709],{"class":268,"line":444},[266,702,703],{"class":351},"        req",[266,705,467],{"class":280},[266,707,708],{"class":362},"headers",[266,710,711],{"class":284},"()\n",[266,713,714,717,720,722,724,727,729],{"class":268,"line":476},[266,715,716],{"class":280},"            .",[266,718,719],{"class":362},"get",[266,721,366],{"class":284},[266,723,413],{"class":412},[266,725,726],{"class":416},"x-plan-key",[266,728,413],{"class":412},[266,730,398],{"class":284},[266,732,734,736,739,741,743,746,748,751,753,756,758,760,763],{"class":268,"line":733},10,[266,735,716],{"class":280},[266,737,738],{"class":362},"and_then",[266,740,366],{"class":284},[266,742,690],{"class":280},[266,744,745],{"class":351},"value",[266,747,690],{"class":280},[266,749,750],{"class":351}," value",[266,752,467],{"class":280},[266,754,755],{"class":362},"to_str",[266,757,484],{"class":284},[266,759,467],{"class":280},[266,761,762],{"class":362},"ok",[266,764,441],{"class":284},[266,766,768,770,773,775,778,780,783],{"class":268,"line":767},11,[266,769,716],{"class":280},[266,771,772],{"class":362},"map",[266,774,366],{"class":284},[266,776,777],{"class":276},"str",[266,779,281],{"class":280},[266,781,782],{"class":351},"to_string",[266,784,398],{"class":284},[266,786,788,790,793,795,797,799,802,805,808,811,814,817,819],{"class":268,"line":787},12,[266,789,716],{"class":280},[266,791,792],{"class":362},"ok_or",[266,794,366],{"class":284},[266,796,583],{"class":276},[266,798,281],{"class":280},[266,800,801],{"class":276},"InvalidValue",[266,803,804],{"class":284}," {",[266,806,807],{"class":351}," reason",[266,809,810],{"class":280},":",[266,812,813],{"class":412}," \"",[266,815,816],{"class":416},"missing plan key",[266,818,413],{"class":412},[266,820,821],{"class":284}," })\n",[266,823,825],{"class":268,"line":824},13,[266,826,827],{"class":284},"    })\n",[266,829,831,833,835,837,839,842,844,847,849],{"class":268,"line":830},14,[266,832,404],{"class":280},[266,834,564],{"class":362},[266,836,366],{"class":284},[266,838,690],{"class":280},[266,840,841],{"class":351},"_req",[266,843,290],{"class":284},[266,845,846],{"class":351}," key",[266,848,690],{"class":280},[266,850,698],{"class":284},[266,852,854,858,860,862,865,867,869,872,874,877],{"class":268,"line":853},15,[266,855,857],{"class":856},"sRxSC","        if",[266,859,846],{"class":351},[266,861,467],{"class":280},[266,863,864],{"class":362},"starts_with",[266,866,366],{"class":284},[266,868,413],{"class":412},[266,870,871],{"class":416},"pro:",[266,873,413],{"class":412},[266,875,876],{"class":284},")",[266,878,698],{"class":284},[266,880,882,885,887,890,892,895,897,899],{"class":268,"line":881},16,[266,883,884],{"class":276},"            RateLimit",[266,886,281],{"class":280},[266,888,889],{"class":362},"per_minute_or_panic",[266,891,366],{"class":284},[266,893,894],{"class":388},"1_000",[266,896,467],{"class":466},[266,898,470],{"class":388},[266,900,398],{"class":284},[266,902,904,907,910],{"class":268,"line":903},17,[266,905,906],{"class":284},"        }",[266,908,909],{"class":856}," else",[266,911,698],{"class":284},[266,913,915,917,919,921,923,925,927,929],{"class":268,"line":914},18,[266,916,884],{"class":276},[266,918,281],{"class":280},[266,920,889],{"class":362},[266,922,366],{"class":284},[266,924,389],{"class":388},[266,926,467],{"class":466},[266,928,470],{"class":388},[266,930,398],{"class":284},[266,932,934],{"class":268,"line":933},19,[266,935,936],{"class":284},"        }\n",[266,938,940],{"class":268,"line":939},20,[266,941,827],{"class":284},[266,943,945,947,949,951,953],{"class":268,"line":944},21,[266,946,404],{"class":280},[266,948,481],{"class":362},[266,950,484],{"class":284},[266,952,395],{"class":280},[266,954,489],{"class":284},[956,957,958],"callout",{"icon":11},[252,959,960,961,965,966,467],{},"Trypema rates are ",[962,963,964],"strong",{},"sticky per key",": the first rate stored for a key stays until its state\nexpires. A rate that changes while the key stays the same is ignored. Put the plan in the key,\nas above, so an upgrade lands in a new bucket. To change an existing key's rate in place, see\n",[967,968,970],"a",{"href":969},"/actix-web/observability#managing-keys","Managing keys",[252,972,973,974,978],{},"The ",[967,975,977],{"href":976},"/actix-web/keys#validating-before-keying","validating extractor example"," shows a\ncomplete version that looks keys up before trusting them.",[247,980,982],{"id":981},"request-costs","Request costs",[252,984,985,986,989],{},"By default every request costs 1. ",[263,987,988],{},"cost_fn"," charges more for expensive requests; a cost of 0\nforwards the request without counting it:",[256,991,993],{"className":258,"code":992,"language":260,"meta":261,"style":261},"use actix_trypema::{Local, TrypemaLimiter, extract::PeerIp};\nuse trypema::{RateLimit, WindowSize};\n\nlet limiter = TrypemaLimiter::builder(Local::new(WindowSize::seconds_or_panic(60))?)\n    .namespace(\"ip\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(100.0))\n    .cost_fn(|req| match req.path() {\n        \"/export\" => 20,   // a heavy report counts as 20 requests\n        \"/healthz\" => 0,   // never counted\n        _ => 1,\n    })\n    .build()?;\n",[263,994,995,1021,1039,1043,1083,1099,1115,1140,1169,1190,1209,1223,1227],{"__ignoreMap":261},[266,996,997,999,1001,1003,1005,1007,1009,1011,1013,1015,1017,1019],{"class":268,"line":269},[266,998,273],{"class":272},[266,1000,277],{"class":276},[266,1002,281],{"class":280},[266,1004,285],{"class":284},[266,1006,94],{"class":276},[266,1008,290],{"class":284},[266,1010,293],{"class":276},[266,1012,290],{"class":284},[266,1014,298],{"class":276},[266,1016,281],{"class":280},[266,1018,303],{"class":276},[266,1020,306],{"class":284},[266,1022,1023,1025,1027,1029,1031,1033,1035,1037],{"class":268,"line":309},[266,1024,273],{"class":272},[266,1026,314],{"class":276},[266,1028,281],{"class":280},[266,1030,285],{"class":284},[266,1032,321],{"class":276},[266,1034,290],{"class":284},[266,1036,326],{"class":276},[266,1038,306],{"class":284},[266,1040,1041],{"class":268,"line":331},[266,1042,334],{"emptyLinePlaceholder":33},[266,1044,1045,1047,1049,1051,1053,1055,1057,1059,1061,1063,1065,1067,1069,1071,1073,1075,1077,1079,1081],{"class":268,"line":337},[266,1046,348],{"class":347},[266,1048,352],{"class":351},[266,1050,355],{"class":280},[266,1052,293],{"class":276},[266,1054,281],{"class":280},[266,1056,363],{"class":362},[266,1058,366],{"class":284},[266,1060,94],{"class":276},[266,1062,281],{"class":280},[266,1064,373],{"class":362},[266,1066,366],{"class":284},[266,1068,378],{"class":276},[266,1070,281],{"class":280},[266,1072,383],{"class":362},[266,1074,366],{"class":284},[266,1076,389],{"class":388},[266,1078,392],{"class":284},[266,1080,395],{"class":280},[266,1082,398],{"class":284},[266,1084,1085,1087,1089,1091,1093,1095,1097],{"class":268,"line":344},[266,1086,404],{"class":280},[266,1088,407],{"class":362},[266,1090,366],{"class":284},[266,1092,413],{"class":412},[266,1094,417],{"class":416},[266,1096,413],{"class":412},[266,1098,398],{"class":284},[266,1100,1101,1103,1105,1107,1109,1111,1113],{"class":268,"line":401},[266,1102,404],{"class":280},[266,1104,429],{"class":362},[266,1106,366],{"class":284},[266,1108,303],{"class":276},[266,1110,281],{"class":280},[266,1112,438],{"class":362},[266,1114,441],{"class":284},[266,1116,1117,1119,1121,1123,1125,1127,1129,1131,1134,1136,1138],{"class":268,"line":424},[266,1118,404],{"class":280},[266,1120,449],{"class":362},[266,1122,366],{"class":284},[266,1124,321],{"class":276},[266,1126,281],{"class":280},[266,1128,889],{"class":362},[266,1130,366],{"class":284},[266,1132,1133],{"class":388},"100",[266,1135,467],{"class":466},[266,1137,470],{"class":388},[266,1139,473],{"class":284},[266,1141,1142,1144,1146,1148,1150,1152,1154,1157,1160,1162,1165,1167],{"class":268,"line":444},[266,1143,404],{"class":280},[266,1145,988],{"class":362},[266,1147,366],{"class":284},[266,1149,690],{"class":280},[266,1151,693],{"class":351},[266,1153,690],{"class":280},[266,1155,1156],{"class":856}," match",[266,1158,1159],{"class":351}," req",[266,1161,467],{"class":280},[266,1163,1164],{"class":362},"path",[266,1166,484],{"class":284},[266,1168,698],{"class":284},[266,1170,1171,1174,1177,1179,1182,1185,1187],{"class":268,"line":476},[266,1172,1173],{"class":412},"        \"",[266,1175,1176],{"class":416},"/export",[266,1178,413],{"class":412},[266,1180,1181],{"class":280}," =>",[266,1183,1184],{"class":388}," 20",[266,1186,290],{"class":284},[266,1188,1189],{"class":340},"   // a heavy report counts as 20 requests\n",[266,1191,1192,1194,1197,1199,1201,1204,1206],{"class":268,"line":733},[266,1193,1173],{"class":412},[266,1195,1196],{"class":416},"/healthz",[266,1198,413],{"class":412},[266,1200,1181],{"class":280},[266,1202,1203],{"class":388}," 0",[266,1205,290],{"class":284},[266,1207,1208],{"class":340},"   // never counted\n",[266,1210,1211,1214,1217,1220],{"class":268,"line":767},[266,1212,1213],{"class":351},"        _ ",[266,1215,1216],{"class":280},"=>",[266,1218,1219],{"class":388}," 1",[266,1221,1222],{"class":284},",\n",[266,1224,1225],{"class":268,"line":787},[266,1226,827],{"class":284},[266,1228,1229,1231,1233,1235,1237],{"class":268,"line":824},[266,1230,404],{"class":280},[266,1232,481],{"class":362},[266,1234,484],{"class":284},[266,1236,395],{"class":280},[266,1238,489],{"class":284},[252,1240,1241,1242,1245,1246,1249],{},"Keep costs at or below the window capacity. The local backend checks before it adds, so a\nrequest costing ",[263,1243,1244],{},"n"," can overshoot the limit by up to ",[263,1247,1248],{},"n - 1",". The Redis and hybrid backends\nreject a request whose cost is more than the capacity left, so a cost above the whole capacity\nis never admitted.",[247,1251,67],{"id":1252},"strategies",[252,1254,1255,1256,1259,1260,1263],{},"The default ",[263,1257,1258],{},"Strategy::Absolute"," admits until the limit, then rejects until capacity frees up.\n",[263,1261,1262],{},"Strategy::Suppressed"," sheds load gradually instead: past a soft limit, a growing share of\nrequests is rejected at random, until the hard limit rejects them all.",[256,1265,1267],{"className":258,"code":1266,"language":260,"meta":261,"style":261},"use std::time::Duration;\n\nuse actix_trypema::{Local, Strategy, TrypemaLimiter, extract::PeerIp};\nuse trypema::{RateLimit, WindowSize};\n\nlet limiter = TrypemaLimiter::builder(Local::new(WindowSize::seconds_or_panic(60))?)\n    .namespace(\"ip\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(600.0))\n    .strategy(Strategy::Suppressed)\n    // Suppressed rejections have no natural wait time; advertise one.\n    .suppressed_retry_hint(Duration::from_secs(5))\n    .build()?;\n",[263,1268,1269,1288,1292,1323,1341,1345,1385,1401,1417,1442,1460,1465,1488],{"__ignoreMap":261},[266,1270,1271,1273,1276,1278,1281,1283,1286],{"class":268,"line":269},[266,1272,273],{"class":272},[266,1274,1275],{"class":276}," std",[266,1277,281],{"class":280},[266,1279,1280],{"class":276},"time",[266,1282,281],{"class":280},[266,1284,1285],{"class":276},"Duration",[266,1287,489],{"class":284},[266,1289,1290],{"class":268,"line":309},[266,1291,334],{"emptyLinePlaceholder":33},[266,1293,1294,1296,1298,1300,1302,1304,1306,1309,1311,1313,1315,1317,1319,1321],{"class":268,"line":331},[266,1295,273],{"class":272},[266,1297,277],{"class":276},[266,1299,281],{"class":280},[266,1301,285],{"class":284},[266,1303,94],{"class":276},[266,1305,290],{"class":284},[266,1307,1308],{"class":276}," Strategy",[266,1310,290],{"class":284},[266,1312,293],{"class":276},[266,1314,290],{"class":284},[266,1316,298],{"class":276},[266,1318,281],{"class":280},[266,1320,303],{"class":276},[266,1322,306],{"class":284},[266,1324,1325,1327,1329,1331,1333,1335,1337,1339],{"class":268,"line":337},[266,1326,273],{"class":272},[266,1328,314],{"class":276},[266,1330,281],{"class":280},[266,1332,285],{"class":284},[266,1334,321],{"class":276},[266,1336,290],{"class":284},[266,1338,326],{"class":276},[266,1340,306],{"class":284},[266,1342,1343],{"class":268,"line":344},[266,1344,334],{"emptyLinePlaceholder":33},[266,1346,1347,1349,1351,1353,1355,1357,1359,1361,1363,1365,1367,1369,1371,1373,1375,1377,1379,1381,1383],{"class":268,"line":401},[266,1348,348],{"class":347},[266,1350,352],{"class":351},[266,1352,355],{"class":280},[266,1354,293],{"class":276},[266,1356,281],{"class":280},[266,1358,363],{"class":362},[266,1360,366],{"class":284},[266,1362,94],{"class":276},[266,1364,281],{"class":280},[266,1366,373],{"class":362},[266,1368,366],{"class":284},[266,1370,378],{"class":276},[266,1372,281],{"class":280},[266,1374,383],{"class":362},[266,1376,366],{"class":284},[266,1378,389],{"class":388},[266,1380,392],{"class":284},[266,1382,395],{"class":280},[266,1384,398],{"class":284},[266,1386,1387,1389,1391,1393,1395,1397,1399],{"class":268,"line":424},[266,1388,404],{"class":280},[266,1390,407],{"class":362},[266,1392,366],{"class":284},[266,1394,413],{"class":412},[266,1396,417],{"class":416},[266,1398,413],{"class":412},[266,1400,398],{"class":284},[266,1402,1403,1405,1407,1409,1411,1413,1415],{"class":268,"line":444},[266,1404,404],{"class":280},[266,1406,429],{"class":362},[266,1408,366],{"class":284},[266,1410,303],{"class":276},[266,1412,281],{"class":280},[266,1414,438],{"class":362},[266,1416,441],{"class":284},[266,1418,1419,1421,1423,1425,1427,1429,1431,1433,1436,1438,1440],{"class":268,"line":476},[266,1420,404],{"class":280},[266,1422,449],{"class":362},[266,1424,366],{"class":284},[266,1426,321],{"class":276},[266,1428,281],{"class":280},[266,1430,889],{"class":362},[266,1432,366],{"class":284},[266,1434,1435],{"class":388},"600",[266,1437,467],{"class":466},[266,1439,470],{"class":388},[266,1441,473],{"class":284},[266,1443,1444,1446,1449,1451,1454,1456,1458],{"class":268,"line":733},[266,1445,404],{"class":280},[266,1447,1448],{"class":362},"strategy",[266,1450,366],{"class":284},[266,1452,1453],{"class":276},"Strategy",[266,1455,281],{"class":280},[266,1457,78],{"class":276},[266,1459,398],{"class":284},[266,1461,1462],{"class":268,"line":767},[266,1463,1464],{"class":340},"    // Suppressed rejections have no natural wait time; advertise one.\n",[266,1466,1467,1469,1472,1474,1476,1478,1481,1483,1486],{"class":268,"line":787},[266,1468,404],{"class":280},[266,1470,1471],{"class":362},"suppressed_retry_hint",[266,1473,366],{"class":284},[266,1475,1285],{"class":276},[266,1477,281],{"class":280},[266,1479,1480],{"class":362},"from_secs",[266,1482,366],{"class":284},[266,1484,1485],{"class":388},"5",[266,1487,473],{"class":284},[266,1489,1490,1492,1494,1496,1498],{"class":268,"line":824},[266,1491,404],{"class":280},[266,1493,481],{"class":362},[266,1495,484],{"class":284},[266,1497,395],{"class":280},[266,1499,489],{"class":284},[252,1501,1502,1503,1505,1506,467],{},"The hard limit is the rate times the provider's hard limit factor (configured on the backend;\nsee ",[967,1504,78],{"href":79},"). Admitted responses carry the current factor in\n",[263,1507,1508],{},"x-ratelimit-suppression",[247,1510,1512],{"id":1511},"skipping-requests","Skipping requests",[252,1514,1515,1518],{},[263,1516,1517],{},"exclude"," forwards matching requests without counting them. Each call adds a predicate, and a\nrequest matching any of them is skipped:",[256,1520,1522],{"className":258,"code":1521,"language":260,"meta":261,"style":261},"use actix_trypema::{Local, TrypemaLimiter, extract::PeerIp};\nuse actix_web::http::Method;\nuse trypema::{RateLimit, WindowSize};\n\nlet limiter = TrypemaLimiter::builder(Local::new(WindowSize::seconds_or_panic(60))?)\n    .namespace(\"ip\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(60.0))\n    .exclude(|req| req.path() == \"/healthz\" || req.path().starts_with(\"/static/\"))\n    .exclude(|req| req.method() == Method::OPTIONS) // CORS preflights\n    .build()?;\n",[263,1523,1524,1550,1569,1587,1591,1631,1647,1663,1687,1744,1783],{"__ignoreMap":261},[266,1525,1526,1528,1530,1532,1534,1536,1538,1540,1542,1544,1546,1548],{"class":268,"line":269},[266,1527,273],{"class":272},[266,1529,277],{"class":276},[266,1531,281],{"class":280},[266,1533,285],{"class":284},[266,1535,94],{"class":276},[266,1537,290],{"class":284},[266,1539,293],{"class":276},[266,1541,290],{"class":284},[266,1543,298],{"class":276},[266,1545,281],{"class":280},[266,1547,303],{"class":276},[266,1549,306],{"class":284},[266,1551,1552,1554,1557,1559,1562,1564,1567],{"class":268,"line":309},[266,1553,273],{"class":272},[266,1555,1556],{"class":276}," actix_web",[266,1558,281],{"class":280},[266,1560,1561],{"class":276},"http",[266,1563,281],{"class":280},[266,1565,1566],{"class":276},"Method",[266,1568,489],{"class":284},[266,1570,1571,1573,1575,1577,1579,1581,1583,1585],{"class":268,"line":331},[266,1572,273],{"class":272},[266,1574,314],{"class":276},[266,1576,281],{"class":280},[266,1578,285],{"class":284},[266,1580,321],{"class":276},[266,1582,290],{"class":284},[266,1584,326],{"class":276},[266,1586,306],{"class":284},[266,1588,1589],{"class":268,"line":337},[266,1590,334],{"emptyLinePlaceholder":33},[266,1592,1593,1595,1597,1599,1601,1603,1605,1607,1609,1611,1613,1615,1617,1619,1621,1623,1625,1627,1629],{"class":268,"line":344},[266,1594,348],{"class":347},[266,1596,352],{"class":351},[266,1598,355],{"class":280},[266,1600,293],{"class":276},[266,1602,281],{"class":280},[266,1604,363],{"class":362},[266,1606,366],{"class":284},[266,1608,94],{"class":276},[266,1610,281],{"class":280},[266,1612,373],{"class":362},[266,1614,366],{"class":284},[266,1616,378],{"class":276},[266,1618,281],{"class":280},[266,1620,383],{"class":362},[266,1622,366],{"class":284},[266,1624,389],{"class":388},[266,1626,392],{"class":284},[266,1628,395],{"class":280},[266,1630,398],{"class":284},[266,1632,1633,1635,1637,1639,1641,1643,1645],{"class":268,"line":401},[266,1634,404],{"class":280},[266,1636,407],{"class":362},[266,1638,366],{"class":284},[266,1640,413],{"class":412},[266,1642,417],{"class":416},[266,1644,413],{"class":412},[266,1646,398],{"class":284},[266,1648,1649,1651,1653,1655,1657,1659,1661],{"class":268,"line":424},[266,1650,404],{"class":280},[266,1652,429],{"class":362},[266,1654,366],{"class":284},[266,1656,303],{"class":276},[266,1658,281],{"class":280},[266,1660,438],{"class":362},[266,1662,441],{"class":284},[266,1664,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683,1685],{"class":268,"line":444},[266,1666,404],{"class":280},[266,1668,449],{"class":362},[266,1670,366],{"class":284},[266,1672,321],{"class":276},[266,1674,281],{"class":280},[266,1676,889],{"class":362},[266,1678,366],{"class":284},[266,1680,389],{"class":388},[266,1682,467],{"class":466},[266,1684,470],{"class":388},[266,1686,473],{"class":284},[266,1688,1689,1691,1693,1695,1697,1699,1701,1703,1705,1707,1709,1712,1714,1716,1718,1721,1723,1725,1727,1729,1731,1733,1735,1737,1740,1742],{"class":268,"line":476},[266,1690,404],{"class":280},[266,1692,1517],{"class":362},[266,1694,366],{"class":284},[266,1696,690],{"class":280},[266,1698,693],{"class":351},[266,1700,690],{"class":280},[266,1702,1159],{"class":351},[266,1704,467],{"class":280},[266,1706,1164],{"class":362},[266,1708,484],{"class":284},[266,1710,1711],{"class":280}," ==",[266,1713,813],{"class":412},[266,1715,1196],{"class":416},[266,1717,413],{"class":412},[266,1719,1720],{"class":280}," ||",[266,1722,1159],{"class":351},[266,1724,467],{"class":280},[266,1726,1164],{"class":362},[266,1728,484],{"class":284},[266,1730,467],{"class":280},[266,1732,864],{"class":362},[266,1734,366],{"class":284},[266,1736,413],{"class":412},[266,1738,1739],{"class":416},"/static/",[266,1741,413],{"class":412},[266,1743,473],{"class":284},[266,1745,1746,1748,1750,1752,1754,1756,1758,1760,1762,1765,1767,1769,1772,1774,1778,1780],{"class":268,"line":733},[266,1747,404],{"class":280},[266,1749,1517],{"class":362},[266,1751,366],{"class":284},[266,1753,690],{"class":280},[266,1755,693],{"class":351},[266,1757,690],{"class":280},[266,1759,1159],{"class":351},[266,1761,467],{"class":280},[266,1763,1764],{"class":362},"method",[266,1766,484],{"class":284},[266,1768,1711],{"class":280},[266,1770,1771],{"class":276}," Method",[266,1773,281],{"class":280},[266,1775,1777],{"class":1776},"sQeA1","OPTIONS",[266,1779,876],{"class":284},[266,1781,1782],{"class":340}," // CORS preflights\n",[266,1784,1785,1787,1789,1791,1793],{"class":268,"line":767},[266,1786,404],{"class":280},[266,1788,481],{"class":362},[266,1790,484],{"class":284},[266,1792,395],{"class":280},[266,1794,489],{"class":284},[247,1796,1798],{"id":1797},"several-limiters-on-one-app","Several limiters on one app",[252,1800,1801],{},"Real APIs often combine limits: a generous per-IP limit everywhere, a strict one on login, and\nper-account quotas on the API. Each is its own limiter with its own namespace. They can share\none backend:",[256,1803,1805],{"className":258,"code":1804,"language":260,"meta":261,"style":261},"use actix_trypema::{Local, TrypemaLimiter, extract::{Header, PeerIp}};\nuse actix_web::{App, web};\nuse trypema::{RateLimit, WindowSize};\n\nlet backend = Local::new(WindowSize::seconds_or_panic(60))?;\n\nlet per_ip = TrypemaLimiter::builder(backend.clone())\n    .namespace(\"ip\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(600.0))\n    .build()?;\n\nlet login = TrypemaLimiter::builder(backend.clone())\n    .namespace(\"login\")\n    .extractor(PeerIp::default())\n    .rate(RateLimit::per_minute_or_panic(5.0))\n    .build()?;\n\nlet per_account = TrypemaLimiter::builder(backend)\n    .namespace(\"account\")\n    .extractor(Header::new(\"x-account-id\")?) // set by your auth middleware\n    .rate(RateLimit::per_minute_or_panic(1_000.0))\n    .build()?;\n\nlet app = App::new()\n    .wrap(per_ip)\n    .service(\n        web::resource(\"/login\")\n            .wrap(login)\n            .route(web::post().to(|| async { \"logged in\" })),\n    )\n    .service(\n        web::scope(\"/api\")\n            .wrap(per_account)\n            .route(\"/orders\", web::get().to(|| async { \"orders\" })),\n    );\n",[263,1806,1807,1842,1863,1881,1885,1918,1922,1949,1965,1981,2005,2017,2021,2046,2063,2079,2103,2115,2119,2140,2157,2189,2214,2227,2232,2251,2266,2277,2299,2312,2357,2363,2372,2393,2407,2454],{"__ignoreMap":261},[266,1808,1809,1811,1813,1815,1817,1819,1821,1823,1825,1827,1829,1831,1834,1836,1839],{"class":268,"line":269},[266,1810,273],{"class":272},[266,1812,277],{"class":276},[266,1814,281],{"class":280},[266,1816,285],{"class":284},[266,1818,94],{"class":276},[266,1820,290],{"class":284},[266,1822,293],{"class":276},[266,1824,290],{"class":284},[266,1826,298],{"class":276},[266,1828,281],{"class":280},[266,1830,285],{"class":284},[266,1832,1833],{"class":276},"Header",[266,1835,290],{"class":284},[266,1837,1838],{"class":276}," PeerIp",[266,1840,1841],{"class":284},"}};\n",[266,1843,1844,1846,1848,1850,1852,1855,1857,1861],{"class":268,"line":309},[266,1845,273],{"class":272},[266,1847,1556],{"class":276},[266,1849,281],{"class":280},[266,1851,285],{"class":284},[266,1853,1854],{"class":276},"App",[266,1856,290],{"class":284},[266,1858,1860],{"class":1859},"s6Ffr"," web",[266,1862,306],{"class":284},[266,1864,1865,1867,1869,1871,1873,1875,1877,1879],{"class":268,"line":331},[266,1866,273],{"class":272},[266,1868,314],{"class":276},[266,1870,281],{"class":280},[266,1872,285],{"class":284},[266,1874,321],{"class":276},[266,1876,290],{"class":284},[266,1878,326],{"class":276},[266,1880,306],{"class":284},[266,1882,1883],{"class":268,"line":337},[266,1884,334],{"emptyLinePlaceholder":33},[266,1886,1887,1889,1892,1894,1896,1898,1900,1902,1904,1906,1908,1910,1912,1914,1916],{"class":268,"line":344},[266,1888,348],{"class":347},[266,1890,1891],{"class":351}," backend ",[266,1893,355],{"class":280},[266,1895,588],{"class":276},[266,1897,281],{"class":280},[266,1899,373],{"class":362},[266,1901,366],{"class":284},[266,1903,378],{"class":276},[266,1905,281],{"class":280},[266,1907,383],{"class":362},[266,1909,366],{"class":284},[266,1911,389],{"class":388},[266,1913,392],{"class":284},[266,1915,395],{"class":280},[266,1917,489],{"class":284},[266,1919,1920],{"class":268,"line":401},[266,1921,334],{"emptyLinePlaceholder":33},[266,1923,1924,1926,1929,1931,1933,1935,1937,1939,1942,1944,1947],{"class":268,"line":424},[266,1925,348],{"class":347},[266,1927,1928],{"class":351}," per_ip ",[266,1930,355],{"class":280},[266,1932,293],{"class":276},[266,1934,281],{"class":280},[266,1936,363],{"class":362},[266,1938,366],{"class":284},[266,1940,1941],{"class":351},"backend",[266,1943,467],{"class":280},[266,1945,1946],{"class":362},"clone",[266,1948,441],{"class":284},[266,1950,1951,1953,1955,1957,1959,1961,1963],{"class":268,"line":444},[266,1952,404],{"class":280},[266,1954,407],{"class":362},[266,1956,366],{"class":284},[266,1958,413],{"class":412},[266,1960,417],{"class":416},[266,1962,413],{"class":412},[266,1964,398],{"class":284},[266,1966,1967,1969,1971,1973,1975,1977,1979],{"class":268,"line":476},[266,1968,404],{"class":280},[266,1970,429],{"class":362},[266,1972,366],{"class":284},[266,1974,303],{"class":276},[266,1976,281],{"class":280},[266,1978,438],{"class":362},[266,1980,441],{"class":284},[266,1982,1983,1985,1987,1989,1991,1993,1995,1997,1999,2001,2003],{"class":268,"line":733},[266,1984,404],{"class":280},[266,1986,449],{"class":362},[266,1988,366],{"class":284},[266,1990,321],{"class":276},[266,1992,281],{"class":280},[266,1994,889],{"class":362},[266,1996,366],{"class":284},[266,1998,1435],{"class":388},[266,2000,467],{"class":466},[266,2002,470],{"class":388},[266,2004,473],{"class":284},[266,2006,2007,2009,2011,2013,2015],{"class":268,"line":767},[266,2008,404],{"class":280},[266,2010,481],{"class":362},[266,2012,484],{"class":284},[266,2014,395],{"class":280},[266,2016,489],{"class":284},[266,2018,2019],{"class":268,"line":787},[266,2020,334],{"emptyLinePlaceholder":33},[266,2022,2023,2025,2028,2030,2032,2034,2036,2038,2040,2042,2044],{"class":268,"line":824},[266,2024,348],{"class":347},[266,2026,2027],{"class":351}," login ",[266,2029,355],{"class":280},[266,2031,293],{"class":276},[266,2033,281],{"class":280},[266,2035,363],{"class":362},[266,2037,366],{"class":284},[266,2039,1941],{"class":351},[266,2041,467],{"class":280},[266,2043,1946],{"class":362},[266,2045,441],{"class":284},[266,2047,2048,2050,2052,2054,2056,2059,2061],{"class":268,"line":830},[266,2049,404],{"class":280},[266,2051,407],{"class":362},[266,2053,366],{"class":284},[266,2055,413],{"class":412},[266,2057,2058],{"class":416},"login",[266,2060,413],{"class":412},[266,2062,398],{"class":284},[266,2064,2065,2067,2069,2071,2073,2075,2077],{"class":268,"line":853},[266,2066,404],{"class":280},[266,2068,429],{"class":362},[266,2070,366],{"class":284},[266,2072,303],{"class":276},[266,2074,281],{"class":280},[266,2076,438],{"class":362},[266,2078,441],{"class":284},[266,2080,2081,2083,2085,2087,2089,2091,2093,2095,2097,2099,2101],{"class":268,"line":881},[266,2082,404],{"class":280},[266,2084,449],{"class":362},[266,2086,366],{"class":284},[266,2088,321],{"class":276},[266,2090,281],{"class":280},[266,2092,889],{"class":362},[266,2094,366],{"class":284},[266,2096,1485],{"class":388},[266,2098,467],{"class":466},[266,2100,470],{"class":388},[266,2102,473],{"class":284},[266,2104,2105,2107,2109,2111,2113],{"class":268,"line":903},[266,2106,404],{"class":280},[266,2108,481],{"class":362},[266,2110,484],{"class":284},[266,2112,395],{"class":280},[266,2114,489],{"class":284},[266,2116,2117],{"class":268,"line":914},[266,2118,334],{"emptyLinePlaceholder":33},[266,2120,2121,2123,2126,2128,2130,2132,2134,2136,2138],{"class":268,"line":933},[266,2122,348],{"class":347},[266,2124,2125],{"class":351}," per_account ",[266,2127,355],{"class":280},[266,2129,293],{"class":276},[266,2131,281],{"class":280},[266,2133,363],{"class":362},[266,2135,366],{"class":284},[266,2137,1941],{"class":351},[266,2139,398],{"class":284},[266,2141,2142,2144,2146,2148,2150,2153,2155],{"class":268,"line":939},[266,2143,404],{"class":280},[266,2145,407],{"class":362},[266,2147,366],{"class":284},[266,2149,413],{"class":412},[266,2151,2152],{"class":416},"account",[266,2154,413],{"class":412},[266,2156,398],{"class":284},[266,2158,2159,2161,2163,2165,2167,2169,2171,2173,2175,2178,2180,2182,2184,2186],{"class":268,"line":944},[266,2160,404],{"class":280},[266,2162,429],{"class":362},[266,2164,366],{"class":284},[266,2166,1833],{"class":276},[266,2168,281],{"class":280},[266,2170,373],{"class":362},[266,2172,366],{"class":284},[266,2174,413],{"class":412},[266,2176,2177],{"class":416},"x-account-id",[266,2179,413],{"class":412},[266,2181,876],{"class":284},[266,2183,395],{"class":280},[266,2185,876],{"class":284},[266,2187,2188],{"class":340}," // set by your auth middleware\n",[266,2190,2192,2194,2196,2198,2200,2202,2204,2206,2208,2210,2212],{"class":268,"line":2191},22,[266,2193,404],{"class":280},[266,2195,449],{"class":362},[266,2197,366],{"class":284},[266,2199,321],{"class":276},[266,2201,281],{"class":280},[266,2203,889],{"class":362},[266,2205,366],{"class":284},[266,2207,894],{"class":388},[266,2209,467],{"class":466},[266,2211,470],{"class":388},[266,2213,473],{"class":284},[266,2215,2217,2219,2221,2223,2225],{"class":268,"line":2216},23,[266,2218,404],{"class":280},[266,2220,481],{"class":362},[266,2222,484],{"class":284},[266,2224,395],{"class":280},[266,2226,489],{"class":284},[266,2228,2230],{"class":268,"line":2229},24,[266,2231,334],{"emptyLinePlaceholder":33},[266,2233,2235,2237,2240,2242,2245,2247,2249],{"class":268,"line":2234},25,[266,2236,348],{"class":347},[266,2238,2239],{"class":351}," app ",[266,2241,355],{"class":280},[266,2243,2244],{"class":276}," App",[266,2246,281],{"class":280},[266,2248,373],{"class":362},[266,2250,711],{"class":284},[266,2252,2254,2256,2259,2261,2264],{"class":268,"line":2253},26,[266,2255,404],{"class":280},[266,2257,2258],{"class":362},"wrap",[266,2260,366],{"class":284},[266,2262,2263],{"class":351},"per_ip",[266,2265,398],{"class":284},[266,2267,2269,2271,2274],{"class":268,"line":2268},27,[266,2270,404],{"class":280},[266,2272,2273],{"class":362},"service",[266,2275,2276],{"class":284},"(\n",[266,2278,2280,2283,2285,2288,2290,2292,2295,2297],{"class":268,"line":2279},28,[266,2281,2282],{"class":276},"        web",[266,2284,281],{"class":280},[266,2286,2287],{"class":362},"resource",[266,2289,366],{"class":284},[266,2291,413],{"class":412},[266,2293,2294],{"class":416},"/login",[266,2296,413],{"class":412},[266,2298,398],{"class":284},[266,2300,2302,2304,2306,2308,2310],{"class":268,"line":2301},29,[266,2303,716],{"class":280},[266,2305,2258],{"class":362},[266,2307,366],{"class":284},[266,2309,2058],{"class":351},[266,2311,398],{"class":284},[266,2313,2315,2317,2320,2322,2325,2327,2330,2332,2334,2337,2339,2342,2345,2347,2349,2352,2354],{"class":268,"line":2314},30,[266,2316,716],{"class":280},[266,2318,2319],{"class":362},"route",[266,2321,366],{"class":284},[266,2323,2324],{"class":276},"web",[266,2326,281],{"class":280},[266,2328,2329],{"class":362},"post",[266,2331,484],{"class":284},[266,2333,467],{"class":280},[266,2335,2336],{"class":362},"to",[266,2338,366],{"class":284},[266,2340,2341],{"class":280},"||",[266,2343,2344],{"class":272}," async",[266,2346,804],{"class":284},[266,2348,813],{"class":412},[266,2350,2351],{"class":416},"logged in",[266,2353,413],{"class":412},[266,2355,2356],{"class":284}," })),\n",[266,2358,2360],{"class":268,"line":2359},31,[266,2361,2362],{"class":284},"    )\n",[266,2364,2366,2368,2370],{"class":268,"line":2365},32,[266,2367,404],{"class":280},[266,2369,2273],{"class":362},[266,2371,2276],{"class":284},[266,2373,2375,2377,2379,2382,2384,2386,2389,2391],{"class":268,"line":2374},33,[266,2376,2282],{"class":276},[266,2378,281],{"class":280},[266,2380,2381],{"class":362},"scope",[266,2383,366],{"class":284},[266,2385,413],{"class":412},[266,2387,2388],{"class":416},"/api",[266,2390,413],{"class":412},[266,2392,398],{"class":284},[266,2394,2396,2398,2400,2402,2405],{"class":268,"line":2395},34,[266,2397,716],{"class":280},[266,2399,2258],{"class":362},[266,2401,366],{"class":284},[266,2403,2404],{"class":351},"per_account",[266,2406,398],{"class":284},[266,2408,2410,2412,2414,2416,2418,2421,2423,2425,2427,2429,2431,2433,2435,2437,2439,2441,2443,2445,2447,2450,2452],{"class":268,"line":2409},35,[266,2411,716],{"class":280},[266,2413,2319],{"class":362},[266,2415,366],{"class":284},[266,2417,413],{"class":412},[266,2419,2420],{"class":416},"/orders",[266,2422,413],{"class":412},[266,2424,290],{"class":284},[266,2426,1860],{"class":276},[266,2428,281],{"class":280},[266,2430,719],{"class":362},[266,2432,484],{"class":284},[266,2434,467],{"class":280},[266,2436,2336],{"class":362},[266,2438,366],{"class":284},[266,2440,2341],{"class":280},[266,2442,2344],{"class":272},[266,2444,804],{"class":284},[266,2446,813],{"class":412},[266,2448,2449],{"class":416},"orders",[266,2451,413],{"class":412},[266,2453,2356],{"class":284},[266,2455,2457],{"class":268,"line":2456},36,[266,2458,2459],{"class":284},"    );\n",[252,2461,2462,2463,2465,2466,511,2468,2470],{},"A request to ",[263,2464,2294],{}," counts against both ",[263,2467,417],{},[263,2469,2058],{},", and is rejected by whichever runs\nout first.",[2472,2473,2474],"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 .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 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 .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 .sMTiH, html code.shiki .sMTiH{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}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 .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 .sQeA1, html code.shiki .sQeA1{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .s6Ffr, html code.shiki .s6Ffr{--shiki-light:#E2931D;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}",{"title":261,"searchDepth":269,"depth":309,"links":2476},[2477,2478,2479,2480,2481,2482],{"id":249,"depth":309,"text":250},{"id":558,"depth":309,"text":559},{"id":981,"depth":309,"text":982},{"id":1252,"depth":309,"text":67},{"id":1511,"depth":309,"text":1512},{"id":1797,"depth":309,"text":1798},"Set rates and windows, give plans different limits, charge expensive requests more, shed load gradually, and stack several limiters.","md",{},{"icon":126},{"title":123,"description":2483},"_Pxs6yFdu9iKeKBqxRMJFzabyrpza9KuOLsB7f7RZmg",[2490,2492],{"title":119,"path":120,"stem":121,"description":2491,"icon":44,"children":-1},"Limit by API key, tenant, user or anything else in the request, with the built-in extractors or your own.",{"title":128,"path":129,"stem":130,"description":2493,"icon":26,"children":-1},"Choose where counts live (in process, in Redis, or both), tune the provider, and decide what happens when Redis fails.",1791663192238]