API Versioning: Strategies for Evolving Without Breaking

APIs are contracts. Breaking changes break trust. But APIs must evolve—new features, better designs, deprecated endpoints. The question isn’t whether to change, but how to change without leaving clients stranded. Why Versioning Matters Without versioning, you have two bad options: Never change: Your API calcifies, accumulating cruft forever Change freely: Clients break unexpectedly, trust erodes Versioning gives you a third path: evolve deliberately, with clear communication and migration windows. Versioning Strategies URL Path Versioning The most explicit approach—version in the URL: ...

February 16, 2026 · 7 min · 1382 words · Rob Washington

Rate Limiting: Protecting Your APIs from Abuse and Overload

Every public API needs rate limiting. Without it, one misbehaving client can take down your entire service—whether through malice, bugs, or just enthusiasm. Rate limiting protects your infrastructure, ensures fair usage, and creates predictable behavior for all clients. The Core Algorithms Fixed Window Count requests in fixed time intervals (e.g., per minute): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class FixedWindowLimiter { constructor(redis, limit, windowSeconds) { this.redis = redis; this.limit = limit; this.windowSeconds = windowSeconds; } async isAllowed(clientId) { const window = Math.floor(Date.now() / 1000 / this.windowSeconds); const key = `ratelimit:${clientId}:${window}`; const count = await this.redis.incr(key); if (count === 1) { await this.redis.expire(key, this.windowSeconds); } return count <= this.limit; } } Pros: Simple, memory-efficient. Cons: Burst at window boundaries. Client could hit 100 requests at 0:59 and 100 more at 1:00. ...

February 16, 2026 · 6 min · 1120 words · Rob Washington