[{"data":1,"prerenderedAt":479},["ShallowReactive",2],{"doc-\u002Ftroubleshooting\u002Frate-limited":3},{"id":4,"title":5,"body":6,"description":469,"edit":470,"extension":471,"meta":472,"navigation":473,"path":474,"seo":475,"stem":476,"vertical":470,"weight":477,"__hash__":478},"content\u002Ftroubleshooting\u002Frate-limited.md","Rate limited",{"type":7,"value":8,"toc":461},"minimark",[9,22,27,42,45,61,65,68,252,263,266,270,277,280,304,308,315,319,326,332,391,398,432,439,443,446,454,457],[10,11,12,13,17,18,21],"p",{},"You are getting ",[14,15,16],"code",{},"429 rate_limited"," on ",[14,19,20],{},"POST \u002Fv1\u002Fingest",". The default\nlimit is 60 requests per minute per device. If your sensor is hitting\nthat, one of the following is true.",[23,24,26],"h2",{"id":25},"_1-the-sensor-is-in-a-fast-loop","1 · The sensor is in a fast loop",[10,28,29,30,33,34,37,38,41],{},"A new firmware that does not back off on success will hammer the ingest\non every loop iteration. Common with DIY ESP32 sketches missing a\n",[14,31,32],{},"delay()",", or ESPHome configs where ",[14,35,36],{},"interval:"," was misread as ",[14,39,40],{},"every loop",".",[10,43,44],{},"Symptom: 200 OK for the first ~60 requests in a minute, then 429 for the\nrest of the minute, then the cycle repeats.",[10,46,47,48,52,53,56,57,60],{},"Fix: enforce a minimum loop interval in the device firmware. We\nrecommend ",[49,50,51],"strong",{},"60 s"," for cold-chain, ",[49,54,55],{},"30 s"," for door-event,\n",[49,58,59],{},"1–5 s"," for energy clamp monitoring (read on, see batching below).",[23,62,64],{"id":63},"_2-you-are-batching-at-the-wrong-layer","2 · You are batching at the wrong layer",[10,66,67],{},"For energy meters that read at 1 Hz, sending one request per second is\nboth wasteful and rate-limit-blocked. Batch on the device side:",[69,70,75],"pre",{"className":71,"code":72,"language":73,"meta":74,"style":74},"language-json shiki shiki-themes github-dark github-dark","POST \u002Fv1\u002Fingest\n{\n  \"device\": \"panel1\",\n  \"measurements\": [\n    { \"ts\": \"2026-05-17T08:22:00Z\", \"type\": \"power\", \"value\": 1240 },\n    { \"ts\": \"2026-05-17T08:22:01Z\", \"type\": \"power\", \"value\": 1255 },\n    { \"ts\": \"2026-05-17T08:22:02Z\", \"type\": \"power\", \"value\": 1268 },\n    …up to 32 entries…\n  ]\n}\n","json","",[14,76,77,93,99,115,124,162,193,224,240,246],{"__ignoreMap":74},[78,79,82,86,90],"span",{"class":80,"line":81},"line",1,[78,83,85],{"class":84},"suv1-","POST \u002Fv",[78,87,89],{"class":88},"s8ozJ","1",[78,91,92],{"class":84},"\u002Fingest\n",[78,94,96],{"class":80,"line":95},2,[78,97,98],{"class":84},"{\n",[78,100,102,105,108,112],{"class":80,"line":101},3,[78,103,104],{"class":88},"  \"device\"",[78,106,107],{"class":84},": ",[78,109,111],{"class":110},"s4wv1","\"panel1\"",[78,113,114],{"class":84},",\n",[78,116,118,121],{"class":80,"line":117},4,[78,119,120],{"class":88},"  \"measurements\"",[78,122,123],{"class":84},": [\n",[78,125,127,130,133,135,138,141,144,146,149,151,154,156,159],{"class":80,"line":126},5,[78,128,129],{"class":84},"    { ",[78,131,132],{"class":88},"\"ts\"",[78,134,107],{"class":84},[78,136,137],{"class":110},"\"2026-05-17T08:22:00Z\"",[78,139,140],{"class":84},", ",[78,142,143],{"class":88},"\"type\"",[78,145,107],{"class":84},[78,147,148],{"class":110},"\"power\"",[78,150,140],{"class":84},[78,152,153],{"class":88},"\"value\"",[78,155,107],{"class":84},[78,157,158],{"class":88},"1240",[78,160,161],{"class":84}," },\n",[78,163,165,167,169,171,174,176,178,180,182,184,186,188,191],{"class":80,"line":164},6,[78,166,129],{"class":84},[78,168,132],{"class":88},[78,170,107],{"class":84},[78,172,173],{"class":110},"\"2026-05-17T08:22:01Z\"",[78,175,140],{"class":84},[78,177,143],{"class":88},[78,179,107],{"class":84},[78,181,148],{"class":110},[78,183,140],{"class":84},[78,185,153],{"class":88},[78,187,107],{"class":84},[78,189,190],{"class":88},"1255",[78,192,161],{"class":84},[78,194,196,198,200,202,205,207,209,211,213,215,217,219,222],{"class":80,"line":195},7,[78,197,129],{"class":84},[78,199,132],{"class":88},[78,201,107],{"class":84},[78,203,204],{"class":110},"\"2026-05-17T08:22:02Z\"",[78,206,140],{"class":84},[78,208,143],{"class":88},[78,210,107],{"class":84},[78,212,148],{"class":110},[78,214,140],{"class":84},[78,216,153],{"class":88},[78,218,107],{"class":84},[78,220,221],{"class":88},"1268",[78,223,161],{"class":84},[78,225,227,231,234,237],{"class":80,"line":226},8,[78,228,230],{"class":229},"sX7ps","    …up",[78,232,233],{"class":229}," to",[78,235,236],{"class":88}," 32",[78,238,239],{"class":229}," entries…\n",[78,241,243],{"class":80,"line":242},9,[78,244,245],{"class":84},"  ]\n",[78,247,249],{"class":80,"line":248},10,[78,250,251],{"class":84},"}\n",[10,253,254,255,258,259,262],{},"One HTTP request, 32 measurements, each with its own ",[14,256,257],{},"ts",". The endpoint\naccepts up to 32 entries per request. Rate-limit budget is per\n",[49,260,261],{},"request",", not per measurement.",[10,264,265],{},"For 1 Hz sampling: batch every 30 s (30 entries), POST once. Budget is\n2 req \u002F min — well under the limit.",[23,267,269],{"id":268},"_3-a-misbehaving-retry-loop","3 · A misbehaving retry loop",[10,271,272,273,276],{},"A 5xx response triggers retry in many client libraries. If the retry\nbackoff is too tight (e.g. ",[14,274,275],{},"requests"," default of 0.2 s between retries),\na brief outage on our side bursts into hundreds of requests per minute\nwhen the service comes back.",[10,278,279],{},"Recommended retry policy:",[281,282,283,287,298],"ul",{},[284,285,286],"li",{},"On 5xx: retry with exponential backoff starting at 1 s,\nmultiplying by 2, capped at 60 s, with jitter.",[284,288,289,290,293,294,297],{},"On 429: respect ",[14,291,292],{},"Retry-After",". Do ",[49,295,296],{},"not"," retry sooner.",[284,299,300,301,303],{},"On 401 \u002F 403 \u002F 422: do ",[49,302,296],{}," retry; the request will never succeed\nunchanged.",[23,305,307],{"id":306},"_4-many-devices-behind-one-nat","4 · Many devices behind one NAT",[10,309,310,311,314],{},"The rate limit is ",[49,312,313],{},"per device",", not per IP — so 50 devices behind one\nNAT can collectively send 3000 req \u002F min. If you are getting 429 with\nonly one logical device, you may be sharing a device id across multiple\nphysical sensors. Each physical sensor should have its own device id\nand token.",[23,316,318],{"id":317},"_5-you-are-using-the-wrong-ingest-path","5 · You are using the wrong ingest path",[10,320,321,322,325],{},"If you have an ESP32 sending 60 readings \u002F min at \u002Fv1\u002Fingest, half of\nthose are the same channel value. Sending the ",[49,323,324],{},"delta"," instead — only\nwhen the reading changes by > X % — drops volume by 80 % in typical\ncold-chain installs.",[10,327,328,329,331],{},"ESPHome supports this with a ",[14,330,324],{}," filter on a sensor:",[69,333,337],{"className":334,"code":335,"language":336,"meta":74,"style":74},"language-yaml shiki shiki-themes github-dark github-dark","sensor:\n  - platform: bme280_i2c\n    temperature:\n      filters:\n        - delta: 0.1   # report only on ≥ 0.1 °C change\n","yaml",[14,338,339,348,361,368,375],{"__ignoreMap":74},[78,340,341,345],{"class":80,"line":81},[78,342,344],{"class":343},"sxg3X","sensor",[78,346,347],{"class":84},":\n",[78,349,350,353,356,358],{"class":80,"line":95},[78,351,352],{"class":84},"  - ",[78,354,355],{"class":343},"platform",[78,357,107],{"class":84},[78,359,360],{"class":110},"bme280_i2c\n",[78,362,363,366],{"class":80,"line":101},[78,364,365],{"class":343},"    temperature",[78,367,347],{"class":84},[78,369,370,373],{"class":80,"line":117},[78,371,372],{"class":343},"      filters",[78,374,347],{"class":84},[78,376,377,380,382,384,387],{"class":80,"line":126},[78,378,379],{"class":84},"        - ",[78,381,324],{"class":343},[78,383,107],{"class":84},[78,385,386],{"class":88},"0.1",[78,388,390],{"class":389},"sJ8bj","   # report only on ≥ 0.1 °C change\n",[10,392,393,394,397],{},"For HACCP you do not want pure delta filtering (the auditor wants regular\nsamples). Combine with a ",[14,395,396],{},"heartbeat"," filter:",[69,399,401],{"className":334,"code":400,"language":336,"meta":74,"style":74},"filters:\n  - delta: 0.1\n  - heartbeat: 60s\n",[14,402,403,410,421],{"__ignoreMap":74},[78,404,405,408],{"class":80,"line":81},[78,406,407],{"class":343},"filters",[78,409,347],{"class":84},[78,411,412,414,416,418],{"class":80,"line":95},[78,413,352],{"class":84},[78,415,324],{"class":343},[78,417,107],{"class":84},[78,419,420],{"class":88},"0.1\n",[78,422,423,425,427,429],{"class":80,"line":101},[78,424,352],{"class":84},[78,426,396],{"class":343},[78,428,107],{"class":84},[78,430,431],{"class":110},"60s\n",[10,433,434,435,438],{},"This means: report on any 0.1 °C change, ",[49,436,437],{},"and"," at least once per 60 s\nregardless of change. Same compliance profile, fraction of the bandwidth.",[23,440,442],{"id":441},"what-to-do-right-now","What to do right now",[10,444,445],{},"If you are in production and getting 429 right now, the fastest\nmitigation is:",[281,447,448,451],{},[284,449,450],{},"Drop the cadence to 120 s temporarily.",[284,452,453],{},"Open a ticket — for short bursts we can raise the limit on your\naccount within 24 h, no questions asked.",[10,455,456],{},"The limit is there to protect the ingest pipeline from misconfigured\nclients, not to upsell. We do not gate \"the actual product\" on it.",[458,459,460],"style",{},"html pre.shiki code .suv1-, html code.shiki .suv1-{--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .s8ozJ, html code.shiki .s8ozJ{--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .s4wv1, html code.shiki .s4wv1{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .sX7ps, html code.shiki .sX7ps{--shiki-default:#FDAEB7;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxg3X, html code.shiki .sxg3X{--shiki-default:#85E89D;--shiki-dark:#85E89D}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":74,"searchDepth":101,"depth":101,"links":462},[463,464,465,466,467,468],{"id":25,"depth":95,"text":26},{"id":63,"depth":95,"text":64},{"id":268,"depth":95,"text":269},{"id":306,"depth":95,"text":307},{"id":317,"depth":95,"text":318},{"id":441,"depth":95,"text":442},"HTTP 429 — what to change",null,"md",{},true,"\u002Ftroubleshooting\u002Frate-limited",{"title":5,"description":469},"troubleshooting\u002Frate-limited",450,"znltlDi5G2X3FXGoPrPbY1uT5xF0CAXnu7qeHYeejn4",1779022955467]