Sobes.tech
Senior

How to implement rate limiting for an external API with RPS restrictions? How do virtual threads/coroutines differ from system threads?

sobes.tech AI

Answer from AI

To implement rate limiting by RPS (requests per second) to an external API in Java, various approaches can be used:

  1. Token Bucket or Leaky Bucket — classic algorithms for rate limiting. For example, using the Guava RateLimiter library:
import com.google.common.util.concurrent.RateLimiter;

RateLimiter rateLimiter = RateLimiter.create(10.0); // 10 requests per second

public void callApi() {
    rateLimiter.acquire(); // blocks until permitted
    // call external API
}
  1. Custom implementation using ScheduledExecutorService — count the number of requests per second and block or delay calls.

  2. Using third-party libraries — for example, Resilience4j, which supports rate limiting and other resilience patterns.


Differences between virtual threads (coroutines) and system threads:

  • System threads (OS threads) — managed by the operating system. They have their own stack, context switching between them is resource-intensive, and their number is limited by OS resources.

  • Virtual threads (e.g., Project Loom in Java) — lightweight threads managed by the JVM, not the OS. They allow creating thousands or millions of concurrent tasks with low memory overhead and context switching costs.

  • Coroutines — a concept of lightweight threads supported at the language level (e.g., Kotlin). They allow suspending and resuming execution without blocking a system thread.

Key differences:

  • Virtual threads and coroutines are more efficient in terms of memory and CPU.
  • Virtual threads integrate with existing Java thread APIs.
  • Coroutines require language and compiler support.

Thus, virtual threads enable scaling concurrency without significant overhead, which is especially useful for IO-bound tasks like external API calls.