Pushed v2.4.0 of bro.js (my zero-boilerplate Express alternative) and figured I'd write up what changed instead of just dumping a changelog.
The Redis integration got a lot less annoying
Used to be you had to wire up your own Redis client and babysit connection state. Now you just drop a redisUrl in the config and most of it's handled for you:
export default {
redisUrl: process.env.REDIS_URL
}
From there:
-
Caching is basically one line.
cache: 60on a route caches the response, and keys get hashed per user + locale + api key so you can't accidentally leak someone else's cached data. - Self-healing cache. If a cached JSON blob ever gets corrupted (happens more than you'd think), it catches the parse error, deletes the bad key, and rebuilds instead of throwing a 500 at your users.
- WebSockets that scale automatically. If it detects a Redis connection it wires up the Socket.io Redis adapter for you, so load-balancing sockets across multiple instances just works instead of silently breaking.
Rate limiter no longer panics when Redis dies
This was the annoying one to get right. If your Redis instance drops or crashes mid-request, the old behavior was... not great. Now it falls back cleanly to a single pre-instantiated in-memory limiter, so your API keeps running and stays rate-limited instead of either falling over or spawning a new limiter per request.
Actual API key auth, not just JWT workarounds
JWTs are fine for user sessions, kind of a pain for CLI tools and service-to-service calls. So:
routes: {
'/admin/stats': {
auth: 'api-key',
apiKey: [process.env.OLD_KEY, process.env.NEW_KEY]
}
}
-
auth: 'api-key'self-documents in the auto-generated Swagger/Scalar docs as a properapiKeyAuthheader scheme. - Passing an array of keys means you can rotate credentials with zero downtime — old key stays valid until you're ready to drop it.
-
auth: ['admin']gives you basic RBAC out of the box. - Helmet is on by default now.
Smaller stuff
-
shutdown()now properly kills both the primary Redis client and the pub/sub duplicates, so your process actually exits instead of hanging on ghost handles. - Fixed the Multer typings, so
single/array/fieldsuploads get real TS autocomplete now instead ofany.
Still no decorators, no nested module system, just file-based routing. Wanted it to hold up under actual production traffic without turning into another framework you need a config generator for.
- GitHub: https://github.com/medyassine/bro.js
- Docs: https://brojs.yessindevs.me
-
Quickstart:
npx create-bro-framework@latest my-api
Would genuinely appreciate anyone trying to break the cache or the limiter — ran it through a decent amount of testing but there's always an edge case I didn't think of.
Top comments (0)