Redis, Round Robin, and API Rate Limits in Torn

Recently, I got an interesting request through an in-game connection in Torn. My Australian spouse messaged me about one of the top factions looking for a dev to help them build a player recognition system to identify potential recruits.

The idea was simple on paper:
Use the Torn API to fetch player stats from today and compare them to the same stats 30 days ago, then compute averages and filter candidates based on specific thresholds.

The Catch: API Rate Limits

Torn’s API has one important constraint:
Each player’s API key is limited to 100 requests per minute.

Since each comparison requires 2 API calls (today + 30 days ago), a single key can load 50 profiles per minute. That’s fine for small batches but not nearly enough for a large-scale scan.

The Solution: Distributed API Keys

The obvious workaround was to buy or borrow API keys from other players.
I ended up with a good number of keys — enough to scale horizontally.

But I didn’t want to max them out. After all, those keys weren’t mine, and I had no interest in getting anyone rate-limited or blocked.

How to Stay Under the Radar?

Torn API

I needed a strategy to hard-limit usage to 50 calls per key per minute.

My first instinct was to use in-memory tracking, but that quickly became a mess. I needed something more persistent, atomic, and scalable.

So I brought in Redis.

How I handle rate limiting with Redis and round-robin key rotation

Torn API

My keys are rotated in a constant round-robin fashion, but before making a request, I check the call history for the current key in Redis. Each key has a queue of timestamps for the last 50 calls. If the oldest timestamp is less than 60 seconds ago, that means the key already hit its 50 calls/minute limit, so I skip it and move on to the next key.

This way, I never exceed the rate limit on any key. The system always uses the “readiest” key available without overloading any single one. It took some trial and error to get the timing and switching smooth, but now it’s fast, fair, and reliable.

Conclusion

When there’s no legacy code, no edge cases, and total control, things feel smooth (especially on not professional work).

This was a perfect reminder that real learning happens when you’re dealing with constraints, solving problems that you haven't thought of until it falls onto you.

There’s always more to figure out. And that’s the part I enjoy the most.

Back to blog