The trouble with API keys that never expire
A key issued years ago, never rotated, and still valid today is not a convenience. It is a liability nobody has actually looked at in years.
A rate limit tied only to an API key makes a quiet assumption: that one key corresponds to one legitimate user, using it in one reasonably predictable way. That assumption breaks down more often than the design assumes. A key can be shared across a team, embedded in a client-side app where many different visitors trigger requests under the same credential, or generated many times over by someone specifically trying to stack several keys to get around a single key's limit.
We rate limit at the network level as well as the key level for exactly this reason. Every network, one /24 block for IPv4 or one /48 block for IPv6, gets a 2,500 request free allowance per day that is shared between keyless use and any keys registered from addresses in that network. A person cannot generate ten keys from the same network and multiply their free allowance by ten, because the network-level ceiling catches that pattern regardless of how many separate keys sit underneath it.
This is not primarily about stopping malicious abuse, though it does that too. It is about keeping the free allowance meaningful for everyone using it honestly. A shared resource like a free tier only stays generous if the generosity does not get quietly siphoned off in bulk by a small number of accounts working around the per-key limit. Network-level quotas keep the math of the free tier closer to what it was actually designed to give out: a real daily allowance per source, not per credential that source happens to hold.
There is a legitimate use case this has to be careful not to punish: multiple genuine users or services legitimately operating from the same network, such as an office, a shared hosting environment, or a large organization behind a small number of public IP addresses. This is exactly why we publish rolling IP slots and give visibility into network usage through quota headers, including a specific header for how many of your key's IP slots are used against the limit. A legitimate team sharing a network can see their real standing rather than discovering a shared ceiling only once they hit it unexpectedly.
Rate limiting only at the key level is simpler to build and explain, and for a lot of APIs it is probably sufficient. For a service with a meaningful free tier specifically, key-only limiting leaves an obvious gap: the free allowance was never meant to be a resource you could multiply by generating more credentials, and a limit that does not account for that is not really protecting the thing it claims to protect. Layering a network-level ceiling on top of the key-level one closes that gap without requiring every legitimate user to prove they are not the exception.