Updated
5 min read

How to Integrate Arcjet Security into Your Stack in Minutes

Security tooling has a habit of turning into infra work. You start with something simple like rate limiting or bot protection. Suddenly you are

How to Integrate Arcjet Security into Your Stack in Minutes

Security tooling has a habit of turning into infra work. You start with something simple like rate limiting or bot protection. Suddenly you are configuring a proxy, updating DNS, or introducing a new layer in front of your app. What should have been a small code change becomes a cross-team project.

Arcjet takes a different approach. It runs inside your runtime as an SDK installed into your application dependencies. That means you integrate it directly into your request handlers, using the same language and framework you already use.

If you are building with Next.js, Remix, Nuxt, NestJS, Express, FastAPI, Flask, Deno, Bun, or a modern edge runtime, integration is typically measured in minutes, not days. This post explains what stacks are supported, what actually changes in your code, what stays the same, and why that design matters.

What Stacks Does Arcjet Support?

Arcjet is designed for modern server runtimes where you control request handling in code.

Today, that includes:

JavaScript and TypeScript

  • Next.js
  • Nuxt
  • Remix
  • NestJS
  • Express
  • Node.js servers
  • Deno
  • Bun
  • Edge runtimes such as Vercel Edge

Python (Beta)

  • FastAPI
  • Flask
  • Other WSGI or ASGI applications

The key requirement is simple: your application processes requests in JavaScript, TypeScript, or Python. Arcjet integrates directly into that execution path. Hoping for another language/stack? Shoot us an email at support@arcjet.com

Why this matters: you do not need to introduce a reverse proxy, sidecar container, or network appliance. There is no traffic redirection layer and no DNS configuration. Security stays inside your application layer, versioned and deployed alongside your code.

The Core Integration Pattern

Regardless of language, the integration model follows the same structure:

  1. Install the SDK
  2. Configure your rules
  3. Call Arcjet inside a request handler
  4. Act on the decision

In JavaScript or TypeScript, it looks like this:

import arcjet from "@arcjet/node";

const aj = arcjet({
  key: process.env.ARCJET_KEY,
  rules: [
    // rate limiting, bot protection, validation rules
  ],
});

export async function handler(request) {
  const decision = await aj.protect(request);
  if (decision.isDenied()) {
    return new Response("Blocked", { status: 403 });
  }
  return new Response("OK");
}

JavaScript SDK Example

In Python, the pattern is conceptually identical. You initialize Arcjet and call it inside your route handler.

For example, in a FastAPI application:

from arcjet import arcjet

aj = arcjet(
    key=os.environ["ARCJET_KEY"],
    rules=[
        # rate limiting, bot detection, etc.
    ],
)

@app.post("/api")
async def handler(request: Request):
    decision = await aj.protect(request)
    if decision.is_allowed():
        return JSONResponse({"status": "blocked"}, status_code=403)
    return JSONResponse({"status": "ok"})

Python SDK example

The structure is the same across languages. You insert a protection step at the beginning of the request lifecycle. This consistency reduces cognitive load. If you work across multiple services or languages, the mental model does not change. Security becomes a predictable part of request handling instead of a framework-specific integration.

What Actually Changes in Your Code?

In most applications, you only modify entry points where requests enter your system. That typically means:

  • API routes
  • Form submission handlers
  • Authentication endpoints
  • Public APIs
  • Webhooks

You initialize Arcjet once and call it at the start of the handler so you’re not rewriting your domain logic, refactoring service layers, or touching your database code. Because the change surface is small. The diff in a pull request is easy to review. Security runs before business logic, and the rest of your application remains untouched. That makes adoption safer and easier to reason about.

Declarative Rules Instead of Ad Hoc Checks

Without a structured approach, security checks tend to spread throughout a codebase. One endpoint implements a basic rate limiter. Another checks IP addresses manually. A third duplicates validation logic in a slightly different way. Over time, that becomes difficult to audit.

Arcjet centralizes these concerns through declarative rule configuration. Instead of scattering defensive logic across handlers, you define rules explicitly and apply them consistently.

This approach has two benefits. First, it makes your security posture easier to understand. You can inspect rule configuration and see exactly how traffic is evaluated. Second, it keeps business logic focused on product behavior instead of defensive infra.

Explicit Decisions Inside Your Control Flow

Arcjet returns a structured decision object for every request. Your application decides what to do with it. You can deny the request, return a specific status code, log the event, or branch behavior based on the reason.

Because the decision is part of your code, it is testable and observable. You can assert on it in integration tests and capture it in logs unlike external proxies that may silently block traffic. Arcjet keeps security decisions inside your application’s control flow so that you retain visibility and flexibility.

What Stays the Same?

One of the biggest concerns when adopting new security tooling is unintended architectural change. There are no DNS changes,  reverse proxy to configure, or global network migration. Arcjet runs inside the same runtime as your application code. With Arcjet, you keep your routing structure, hosting provider, deployment pipeline, database, and authentication system. Ultimately, minimizing infra change reduces risk, and teams are far more likely to adopt security controls when they do not require coordinated changes across networking, DevOps, and platform engineering.

How It Looks Across Frameworks

Although the core integration pattern is the same, the exact insertion point depends on your framework:

  • Next.js: inside API routes, route handlers, or server functions
  • Remix: inside loaders and actions
  • NestJS: inside controllers or guards
  • Express: as early middleware in the request chain
  • FastAPI: inside route handlers
  • Flask: inside standard request handlers

In every case, Arcjet runs at the request boundary, before your business logic executes. That placement is intentional. It ensures security decisions are made early, consistently, and in a way that does not require restructuring your application. As teams evolve their architecture or split services across languages, the integration model stays consistent. Security remains part of application code rather than being tied to a specific framework or infra setup.

Incremental Adoption

You do not need to protect your entire application at once. A common approach is to start with high-risk or high-traffic endpoints such as authentication routes or public APIs. Once validated, you expand coverage to forms, webhooks, and other exposed routes. Because rules live in code, changes can be reviewed, tested, and deployed gradually. Incremental rollout reduces blast radius, so you can evaluate behavior route by route instead of introducing a global change that affects all traffic at once.

Integration Should Feel Routine

For most teams, the process looks like this:

  • Install the SDK
  • Protect a single route
  • Start in DRY_RUN mode (docs here)
  • Deploy
  • Switch to LIVE mode
  • Expand coverage

There is no migration window and no infra reconfig, so security becomes another dependency you add intentionally and review like any other code change, why? Because security should just be another feature

That simplicity is what makes adoption realistic. When integration is straightforward and controlled, teams are more likely to implement protections early instead of postponing them. Arcjet is designed to reinforce your stack, not reshape it. By keeping security inside your application layer, integration becomes a normal part of development rather than a separate infra project.

Subscribe by email

Get the full posts by email every week.