---
title: "Discussion on \"Distributed Rate Limiting: Your Effective Limit Isn't Your Config\" | Hashnode"
description: "Discussion on \"Distributed Rate Limiting: Your Effective Limit Isn't Your Config\". Per-pod counters, fixed-window edges, and the wrong key quietly change the limit you enforce. Here's the math, the fixes, and a test you can run in staging."
url: "https://hashnode.com/posts/distributed-rate-limiting-effective-limit/6af6977ee0fa0b84b693d1e2"
---

[Feed](https://hashnode.com/feed) /

Discussion

# [Distributed Rate Limiting: Your Effective Limit Isn't Your Config](https://simplyexplained.hashnode.dev/distributed-rate-limiting-effective-limit?utm_source=hashnode&utm_medium=feed)

Per-pod counters, fixed-window edges, and the wrong key quietly change the limit you enforce. Here's the math, the fixes, and a test you can run in staging.

18h ago · 12 min read · simplyexplained.hashnode.dev  
Read the article

-   [#system-design](https://hashnode.com/tag/system-design)
-   [#backend](https://hashnode.com/tag/backend)
-   [#api](https://hashnode.com/tag/api)
-   [#redis](https://hashnode.com/tag/redis)
-   [#kubernetes](https://hashnode.com/tag/kubernetes)

## Written by

[Adam Jaber](https://hashnode.com/@adamjaber)

@adamjaber · Delhi, India

  
[View profile](https://hashnode.com/@adamjaber)

Senior engineer. How AI and software work — and where they quietly break.

I'm a senior software engineer. I write Simply Explained, a plain-English breakdown of how AI and software actually work, and the quiet ways they break: AI fixes that hide bugs, agents that pick the wrong tool, health checks that take down healthy servers. One symptom, one analogy, one fix per piece. New here? Start with the pinned Start Here guide, or get one breakdown a week by email.

## Responses 1

Markdown supported · ⌘↵ to post

[Mike Dabydeen](https://hashnode.com/@firelinks)

[10h ago](https://hashnode.com/posts/distributed-rate-limiting-effective-limit/6af6977ee0fa0b84b693d1e2/comment/6af70049f758036b040a3fed)

I'd have the Lua script return the wait time, because window minus elapsed tells a refused client the wrong thing about a sliding window. With the weighted estimate, capacity comes back gradually, at prev/window per second, about 1.7 requests per second in your 100-per-minute example. A client refused because of last window's weight is often allowed again within a second or two, yet Retry-After sends it to the boundary. Every client refused during that minute gets the same boundary, so they all come back together, and the edge burst you removed returns through the retry path.

Inside the script, when estimate >= limit and prev > 0, the wait is (estimate - limit) \* window / prev, rounded up with a one-second minimum and capped at the time left in the window. One small thing in the caller too: int() truncates, so a client refused at 30.4 seconds is told 29 and arrives just before the reset. math.ceil fixes that.
