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.

May 9, 2026·5 min read

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.

npm install securenow

# Update your start command:
node -r securenow/firewall-only server.js

A known-bad IP feed refreshed hourly, plus your own blocklist. Sub-millisecond per request. Free for a 14-day trial, then $99 per app per month.

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.

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

Block an IP, a Range or One Route Without a Deploy (Node.js)

Block one IP, a CIDR range, or a single route and method in a Node.js app within seconds, with no code change: setup, scoping, CLI, MCP, verification and undo.

Oct 27
11 Signs Your AI-Built App Needs a Security Audit

Built your app with a coding agent? 11 warning signs it needs a security audit, each checkable in five minutes, and how to run the full audit yourself.

Oct 26
AI Security Audit Part 1: Set Up Your Agent to Audit Code

Part 1 of the AI security audit series: set up an AI coding agent to audit your app locally, connect SecureNow, and run your first threat-model pass.

Jul 24