Basic API Rate-Limiting

It is likely that you are developing some form of (web/RESTful) API, and in case it is publicly-facing (or even when it’s internal), you normally want to rate-limit it somehow. That is, to limit the number of requests performed over a period of time, in order to save resources and protect from abuse. This can probably be achieved on web-server/load balancer level with some clever configurations, but usually you want the rate limiter to be client-specific (i.e. each client of your API sohuld have a separate rate limit), and the way the client is identified varies. It’s probably still possible to do it on the load balancer, but I think it makes sense to have it on the application level. I’ll use spring-mvc for the example, but any web framework has a good way to plug an interceptor. So here’s an example of a spring-mvc interceptor: @Component public class RateLimitingInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = LoggerFactory.getLogger(RateLimitingInterceptor.class); @Value("${rate.limit.enabled}") private boolean enabled; @Value("${rate.limit.hourly.limit}") private int hourlyLimit; private Map<String, Optional<SimpleRateLimiter>> limiters = new ConcurrentHashMap<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!enabled) { return true; } String clientId = request.getHeader("Client-Id"); // let non-API requests pass if (clientId == null) { return true; } SimpleRateLimiter rateLimiter = getRateLimiter(clientId); boolean allowRequest = limiter.tryAcquire(); if (!allowRequest) { response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); } response.addHeader("X-RateLimit-Limit", String.valueOf(hourlyLimit)); return allowRequest; } private SimpleRateLimiter getRateLimiter(String clientId) { if (limiters.containsKey(clientId)) { return limiters.get(clientId); } else { synchronized(clientId.intern()) { // double-checked locking to avoid multiple-reinitializations if (limiters.containsKey(clientId)) { return limiters.get(clientId); } SimpleRateLimiter rateLimiter = createRateLimiter(clientId); limiters.put(clientId, rateLimiter); return rateLimiter; } } } @PreDestroy public void...

Traditional Web Apps And RESTful APIs

When we are building web applications these days, it is considered a best practice to expose all our functionality as a RESTful API and then consume it ourselves. This usually goes with a rich front-end using heavy javascript, e.g. Angular/Ember/Backbone/React. But a heavy front-end doesn’t seem like a good default – applications that require the overhead of a conceptually heavy javascript framework are actually not in the majority. The web, although much more complicated, is still not just about single-page applications. Not to mention that if you are writing a statically-typed backend, you would either need a dedicated javascript team (no necessarily a good idea, especially in small companies/startups), or you have to write in that … not-so-pleasant language. And honestly, my browsers are hurting with all that unnecessary javascript everywhere, but that’s a separate story. The other option for having yourself consume your own RESTful API is to have a “web” module, that calls your “backend” module. Which may be a good idea, especially if you have different teams with different specialties, but the introduction of so much communication overhead for the sake of the separation seems at least something one should think twice before doing. Not to mention that in reality release cycles are usually tied, as you need extra effort to keep the “web” and “backend” in proper sync (“web” not requesting services that the “backend” doesn’t have yet, or the “backend” not providing a modified response model that the “web” doesn’t expect). As in my defence of monoliths, I’m obviously leaning towards a monolithic application. I won’t repeat the other post, but the idea is...