·3 min read

Traffic Management for Next.js Apps Using Vercel Edge and Upstash Edge Flags

Enes AkarEnes AkarCofounder @Upstash

In this post, we will show how to block the traffic to your web app from a country. You can apply the same logic to manage traffic with other filters (IP address, user-agent etc). We aim a decoupled, lightweight and dynamic solution:

  • I should not need to update and deploy code to update country.
  • It should have minimum overhead and cost on my application.

We will use Vercel Edge Middleware and Upstash Edge Flags.

Vercel Edge Middleware

Vercel Edge middleware is a code that intercepts the web requests before being processed by backend. We will use it to check the country and user agent because:

  • It is fast and cheap.
  • Decoupled from your application.

Upstash Edge Flags

Indeed you can check country and block traffic with a simple if statement in your edge middleware code as below:

const BLOCKED_COUNTRY = "BAD_COUNTRY";
 
export function middleware(req: NextRequest) {
  const country = req.geo.country;
 
  if (country === BLOCKED_COUNTRY) {
    return new Response("Blocked ", { status: 451 });
  }
  return new Response(`Greetings`);
}

So why do we need edge flags? Edge flags will enable us to manage the rules without updating the code.

Let’s start..

Step 1: Redis and Edge Flags Setup

Create a Redis database on Upstash Console. For best performance, select global and the regions that users likely to be.

Edge-Flags

Go to Edge flags page and select the database you have just created. Create a new flag with a name blockTraffic. Then add a rule for blocked countries: Country is in array United States -> on

Save and enable the flag.

Edge-Flags

The above flag will be enabled if the request is originating from the United States.

Step 2: Next.js Project Setup

Create a Next.js application.

npx create-next-app@latest --typescript

Install @upstash packages:

$ npm install @upstash/edge-flags @upstash/redis

Create middleware.ts (top level in your project folder):

/middleware.ts
import { NextRequest, NextResponse } from "next/server";
import { Redis } from "@upstash/redis";
import { Client as EdgeFlags } from "@upstash/edge-flags";
 
const edgeFlags = new EdgeFlags({ redis: Redis.fromEnv() });
export default async function middleware(
  req: NextRequest
): Promise<NextResponse> {
  const enabled = await edgeFlags.getFlag("blockTraffic", req.geo ?? {});
 
  if (!enabled) {
    const url = new URL(req.url);
    url.pathname = "/blocked";
    return NextResponse.rewrite(url);
  }
 
  return NextResponse.next();
}
 
export const config = {
  matcher: "/",
};

Let's create a page for the blocked:

pages/blocked.tsx
import styles from "@/styles/Home.module.css";
 
export default function Blocked() {
  return (
    <div>
      <main className={styles.main}>
        <h3>Access blocked.</h3>
      </main>
    </div>
  );
}

That's all! Now you can deploy the app to Vercel: vercel deploy

Make sure to add the environment variables to Vercel either by copying them from the Upstash console or by using the Upstash integration.

Vercel

Visit the page, you should be redirected to the blocked page if you are in US. Test different countries using VPN.

Geolocation in development

Geolocation data is not avallable locally. You have to deploy to Vercel to test it the app.

Edge flags documentation

Vercel Edge middleware