Design the rate limiter in front of a busy API platform. Every incoming call is checked before it runs: read the counter for its key's current window, increment it, answer allow-or-throttle. A small dashboard endpoint reads a key's current usage back out.
The check rides the critical path of every request the platform serves, so its p99 budget is 8 milliseconds — and every check is a write. There is nothing here for a cache to absorb: a counter you didn't increment is a limit you didn't enforce. Every millisecond between the client and the counter — an extra tier, a coordination round-trip — is charged against a budget that has none to spare.
Before you spend anything on durability, read what the contract actually asks. If a node crashes and takes its last minute of counters with it, a few clients briefly sneak past their limits and nobody files a ticket. What that minute of forgiveness buys you is the whole problem.