How to Block Bot Traffic in Fastify With No Extra Infra
Fastify hooks (onRequest) and the SecureNow preload both work cleanly. Here's the production setup for IP blocking and user-agent filtering.
How to Block Bot Traffic in Fastify With No Extra Infra
Fastify gives you onRequest hooks for the fast path of request handling. Combined with the SecureNow preload, you have two clean options.
Option 1: SecureNow preload (recommended)
npm install securenow
# Update your start command:
node -r securenow/firewall-only server.js
500k IPs blocked, hourly refresh, automatic crawler allowlisting. Sub-millisecond per request. Free.
Option 2: Fastify onRequest hook
import Fastify from 'fastify';
const app = Fastify();
const BLOCKED_IPS = new Set(['185.220.101.42']);
const BAD_UA = /sqlmap|nikto|acunetix|masscan|python-requests/i;
const GOOD_BOTS = /googlebot|bingbot|gptbot|claudebot|perplexitybot/i;
app.addHook('onRequest', async (req, reply) => {
const ip = req.headers['x-forwarded-for']?.toString().split(',')[0]?.trim() || req.ip;
const ua = req.headers['user-agent'] || '';
if (GOOD_BOTS.test(ua)) return;
if (BLOCKED_IPS.has(ip)) return reply.code(403).send('Forbidden');
if (BAD_UA.test(ua)) return reply.code(403).send('Forbidden');
});
This runs before any route handler. Blocked requests get a 403 with no further processing.
Allowlisting trusted proxies
Configure trust proxy properly:
const app = Fastify({
trustProxy: 1, // or true, depending on topology
});
Without this, req.ip is the load balancer's IP, not the user's.
Verifying
npx securenow firewall status
Or via curl:
curl -i https://yourapp.com/ -H "User-Agent: sqlmap/1.5.7"
Combining with @fastify/rate-limit
npm install @fastify/rate-limit
import rateLimit from '@fastify/rate-limit';
await app.register(rateLimit, {
max: 100,
timeWindow: '1 minute',
});
Bot blocking + rate limiting + IP-reputation firewall = three layers of defense, ~5 minutes of setup.
Related
Frequently Asked Questions
Should I use onRequest or preHandler?
onRequest. It runs before payload parsing, so blocked requests don't waste CPU on body parsing. preHandler is the right place for auth-style checks that need parsed bodies.
Does the SecureNow preload work with Fastify?
Yes. Fastify uses Node's HTTP server; the preload sits below it. No Fastify-specific config needed.
What about Fastify v5?
Same hooks, same preload behavior. The plugin API changed slightly but `onRequest` is unchanged.
Can I use this with @fastify/rate-limit?
Yes — they're complementary. Bot blocking removes obvious bad traffic; rate-limit handles per-IP request budgets for everyone else.
Recommended reading
Part 1 of the AI Security Auditing series. Set up an AI coding agent to audit your application's security locally — install SecureNow, connect your account, and run your first threat-model pass in minutes.
Jul 24A practical, end-to-end guide to auditing your application's security with an AI coding agent — find vulnerabilities at the code level, build detections at the runtime level, and never upload your codebase to do it.
Jul 24Part 2 of the AI Security Auditing series. Use an AI agent to audit your login, session, MFA, password-reset and magic-link flows for account-takeover paths — then catch the attempts in live traffic.
Jul 23