How to Secure Your Koa App with SecureNow — Full-Stack Observability for Node.js APIs

Complete walkthrough for adding security monitoring to your Koa.js API with the securenow npm package. Covers CLI login, free trial setup, body capture, PM2 deployment, Docker, and trace verification.

Lhoussine
Mar 26, 2026·8 min read
getting started securenow koa

How to Secure Your Koa App with SecureNow — Full-Stack Observability for Node.js APIs

Koa gives you a minimal, expressive foundation for building APIs — but once you are serving real traffic, you need more than elegant middleware composition. You need to know what requests are hitting your routes, whether they are benign, and how your service behaves under pressure.

SecureNow plugs into your Koa application at the Node.js runtime level, capturing every HTTP request as an OpenTelemetry trace. Those traces feed a security analysis engine that surfaces SQL injection attempts, credential stuffing, API abuse, and anomalous traffic patterns — all without adding a single line of middleware.

This guide walks you through the full setup: installing the package, authenticating with the CLI, creating an application on the free trial, configuring environment variables, instrumenting your Koa app (with full body capture), and deploying to production.

...

Prerequisites

  • Node.js 18+ installed
  • An existing Koa project with koa-bodyparser (or willingness to scaffold one)
  • A terminal and a browser

No SecureNow account yet? The CLI handles signup for you.

...

Step 1: Install the Package

From your project directory:

npm install securenow

This single package includes the OpenTelemetry SDK, auto-instrumentations for Node.js, an OTLP exporter, the SecureNow CLI, and optional console-log forwarding. Koa and its ecosystem packages should already be in your project.

...

Step 2: Log In via the CLI

Authenticate with SecureNow:

npx securenow login

A browser tab opens at app.securenow.ai where you can sign up or log in. The token is saved to ~/.securenow/credentials.json and authorizes all subsequent CLI commands.

Prefer a non-interactive flow? Generate a CLI token from your dashboard at Settings → CLI Token, then run:

npx securenow login --token YOUR_TOKEN

Verify you are logged in:

npx securenow whoami
...

Step 3: Create an Application (Free Trial)

Every monitored application gets a unique identifier (the app key). Create one:

npx securenow apps create my-koa-api

When prompted to pick a ClickHouse instance, choose Free Trial — this gives you a managed OTLP collector at https://freetrial.securenow.ai:4318 at no cost and with no credit card.

After creation:

✔ Application created

  SECURENOW_APPID=c3d4e5f6-a7b8-9012-3456-789abcdef012
  SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318

Add these to your .env file.

Set the new app as your default:

npx securenow config set defaultApp c3d4e5f6-a7b8-9012-3456-789abcdef012
...

Step 4: Configure Environment Variables

Create (or update) a .env file in your project root:

SECURENOW_APPID=c3d4e5f6-a7b8-9012-3456-789abcdef012
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
SECURENOW_LOGGING_ENABLED=1
SECURENOW_CAPTURE_BODY=1
VariablePurpose
SECURENOW_APPIDIdentifies your app in the dashboard. Use the key from Step 3.
SECURENOW_INSTANCEOTLP collector URL. Free trial default shown above.
SECURENOW_LOGGING_ENABLEDSet to 1 to forward console.log/warn/error as OTel logs.
SECURENOW_CAPTURE_BODYSet to 1 to attach request bodies to trace spans. Koa with koa-bodyparser supports this fully. Sensitive fields are automatically redacted.
...

Step 5: Instrument Your Koa App

You have two options — pick whichever fits your workflow.

Option A: Require at the Top of Your Entry File (Recommended)

Add require('securenow/register') as the very first line of your entry file, before any other imports:

require('securenow/register');
require('securenow/console-instrumentation');

const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');

const app = new Koa();
const router = new Router();

app.use(bodyParser());

router.get('/health', (ctx) => {
  ctx.body = { status: 'ok', timestamp: new Date().toISOString() };
});

router.post('/tasks', (ctx) => {
  const { title, description, priority } = ctx.request.body;
  if (!title) {
    ctx.status = 400;
    ctx.body = { error: 'title is required' };
    return;
  }
  const task = { id: Date.now(), title, description, priority, createdAt: new Date().toISOString() };
  ctx.status = 201;
  ctx.body = task;
});

app.use(router.routes());
app.use(router.allowedMethods());

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Koa server running on port ${PORT}`);
});

securenow/register starts the OpenTelemetry SDK, reads your .env, and auto-instruments HTTP, Koa, @koa/router, database drivers, and more. securenow/console-instrumentation forwards console.* calls as OTel log records so they appear alongside your traces.

Option B: Zero Code Changes with the Preload Flag

If you prefer not to modify your source code, preload the modules via Node's -r flag:

node -r securenow/register -r securenow/console-instrumentation app.js

Or in your package.json:

{
  "scripts": {
    "start": "node app.js",
    "start:observe": "node -r securenow/register -r securenow/console-instrumentation app.js"
  }
}
...

Step 6: Start and Verify

Run your app:

node app.js

You should see confirmation in your terminal:

[securenow] OTel SDK started → https://freetrial.securenow.ai:4318/v1/traces
[securenow] 📋 Logging: ENABLED → https://freetrial.securenow.ai:4318/v1/logs
[securenow] Console instrumentation installed
Koa server running on port 3000

Generate some traffic:

curl http://localhost:3000/health
curl -X POST http://localhost:3000/tasks -H "Content-Type: application/json" -d '{"title":"Review PR","priority":"high"}'

Then check your dashboard:

npx securenow status

Your app should appear as protected. Browse traces from the terminal:

npx securenow traces

Or open app.securenow.ai to explore traces, logs, security issues, and analytics.

...

Bonus: Useful CLI Commands

Once your app is instrumented, the CLI becomes your terminal-based control plane:

CommandWhat It Does
securenow tracesList recent traces
securenow traces show <traceId>Inspect a single trace
securenow traces analyze <traceId>AI-powered trace analysis
securenow logsList recent logs
securenow issuesView detected security issues
securenow analyticsTraffic and performance analytics
securenow ip <address>Look up an IP address
securenow blocklist add <ip>Block a malicious IP
securenow alerts rulesManage alert rules
securenow forensicsRun natural-language forensic queries
...

Production Deployment with PM2

For production, use PM2 with an ecosystem config:

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'my-koa-api',
    script: './app.js',
    instances: 4,
    exec_mode: 'cluster',
    node_args: '-r securenow/register -r securenow/console-instrumentation',
    env: {
      SECURENOW_APPID: 'c3d4e5f6-a7b8-9012-3456-789abcdef012',
      SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
      SECURENOW_LOGGING_ENABLED: '1',
      SECURENOW_CAPTURE_BODY: '1',
      SECURENOW_NO_UUID: '1',
      NODE_ENV: 'production',
    }
  }]
};
pm2 start ecosystem.config.js

Setting SECURENOW_NO_UUID=1 ensures all cluster workers report under the same service name.

...

Docker Deployment

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ENV SECURENOW_APPID=my-koa-api
ENV SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
ENV SECURENOW_LOGGING_ENABLED=1
ENV SECURENOW_CAPTURE_BODY=1
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "app.js"]

If you used Option B (preload flag), update the CMD:

CMD ["node", "-r", "securenow/register", "-r", "securenow/console-instrumentation", "app.js"]
...

What SecureNow Detects Automatically

Once traces are flowing, SecureNow watches for:

  • SQL injection — malicious patterns in query parameters and request bodies
  • XSS attempts — script injection in user input
  • Credential stuffing — high-velocity failed authentication attempts
  • API abuse — unusual request patterns, rate-limit evasion, unauthorized endpoint access
  • Anomalous traffic — AI-powered detection of behavioral outliers
  • Supply-chain signals — unexpected outbound calls from your service
  • Performance degradation — slow queries, high error rates, latency spikes

With SECURENOW_CAPTURE_BODY=1 enabled, SecureNow can also analyze request payloads for injection patterns, giving you deeper visibility into POST and PUT requests hitting your Koa routes.

...

Recap

StepCommand / ActionTime
Installnpm install securenow10 s
Loginnpx securenow login20 s
Create appnpx securenow apps create my-koa-api15 s
ConfigureAdd env vars to .env (body capture ON)30 s
InstrumentAdd require('securenow/register') or use -r flag30 s
Verifynpx securenow status10 s

Six steps, under five minutes, zero middleware changes. Your Koa API is now observable and protected.

...

Next Steps

Happy shipping — and happy securing.

Frequently Asked Questions

Does SecureNow capture request bodies with Koa?

Yes. Unlike some frameworks with streaming parsers, Koa paired with koa-bodyparser makes the parsed body available on ctx.request.body before route handlers execute. Set SECURENOW_CAPTURE_BODY=1 to attach request payloads to trace spans. Sensitive fields like passwords and tokens are redacted automatically.

Do I need to add any Koa middleware for SecureNow?

No. SecureNow instruments your application at the Node.js runtime level via the -r preload flag or a require() call. No custom Koa middleware is needed — your existing middleware stack remains untouched.

Will SecureNow work with @koa/router and koa-bodyparser?

Yes. SecureNow's auto-instrumentation recognizes @koa/router (and koa-router) routes, so trace spans include the matched route pattern (e.g., /tasks/:id) rather than raw paths. koa-bodyparser is fully compatible with body capture.

Can I run SecureNow with Koa in PM2 cluster mode?

Yes. Pass -r securenow/register in node_args in your PM2 ecosystem config and set SECURENOW_NO_UUID=1 so all cluster workers report under the same service name in the dashboard.

Recommended reading

Getting Started with SecureNow and Nuxt 3 — Add Security Monitoring in Under 2 Minutes

A hands-on walkthrough for adding security observability to a Nuxt 3 app using the securenow npm package and official Nuxt module. Covers installation, nuxt.config.ts setup, environment variables, optional tuning, deployment targets, CLI verification, and troubleshooting.

Apr 2
One Flag to Trace Them All — `-r securenow/register` Now Works for ESM and CJS

Stop juggling --require and --import flags. securenow/register now auto-registers the ESM loader hook via module.register() on Node >=20.6, so a single -r flag is all you need for both CommonJS and ESM apps.

Apr 2
Add Security Monitoring to a Next.js App with SecureNow — Traces, Logs, and Body Capture on AWS

Step-by-step guide to integrating SecureNow into a self-hosted Next.js application on AWS EC2. Covers installation, instrumentation, environment configuration, verifying traces and logs, enabling request body capture, and creating alert rules.

Mar 29
deploy nextjs hacker news aws securenow