Supabase Middleware 1.0

Sep 30, 2026

What's new#

@supabase/middleware 1.0.0 is on npm and JSR under the latest tag. From 1.0 the package follows semantic versioning: breaking changes ship only in a new major.

It is a small, MIT-licensed engine for per-request logic on Web Fetch handlers:

  • defineMiddleware writes one piece of per-request logic. It contributes one typed key to a shared ctx.
  • pipeline([...], handler) runs several in order and returns the fetch handler. Middleware also nest directly, so pipeline is optional.
  • The handler sees every upstream key, correctly typed. Duplicate keys fail to compile, and so does a middleware placed before its prerequisite.
  • Any middleware can return a Response and stop the chain, or read and change the response on the way out.
  • Two middleware ship with the engine: withCors and withFeatureFlag. Everything else is yours, or comes from a package.

The engine runs wherever fetch runs: Supabase Edge Functions, Vercel Functions, Cloudflare Workers, Deno, Bun, and Node 22 or newer. Inside Hono, H3, Elysia, NestJS, or TanStack Start, the same middleware runs through a short, typechecked bridge you copy into your app. No adapter package, no new dependency. See the frameworks guide.

@supabase/server is built on the engine and ships the Supabase middleware. withSupabase(config) with no handler is a pipeline entry; withSupabase(config, handler) wraps a single handler. Entries before it in the array run ahead of the auth gate, and entries after it receive the Supabase context. The @supabase/server/middleware/* subpaths export the pieces on their own: withClaims, withRequiredClaims, withSupabaseClient, withSupabaseAdminClient, withPostgresClient, and withPostgresAdminClient. withOAuthProtectedResource answers OAuth discovery for MCP clients. All of them are stable as of @supabase/server 1.9.0.

How to use it#


_10
npm install @supabase/middleware

On Edge Functions, import it directly. This example answers OAuth discovery for MCP clients, verifies the caller's token, and hands the handler a Supabase client scoped to that user. The Bring your own MCP guide builds a full MCP server on the same two entries:


_14
import { pipeline } from 'npm:@supabase/middleware@1'
_14
import { withOAuthProtectedResource, withSupabase } from 'npm:@supabase/server@1'
_14
_14
Deno.serve(
_14
pipeline(
_14
// 1. OAuth discovery for MCP clients, 2. verify the user's token and scope a client to them
_14
[withOAuthProtectedResource(), withSupabase({ auth: 'user' })],
_14
async (req, { supabase }) => {
_14
// RLS scopes this query to the signed-in user
_14
const { data } = await supabase.from('tasks').select('id, title')
_14
return Response.json(data)
_14
},
_14
),
_14
)

Writing your own is one call:


_10
import { defineMiddleware } from '@supabase/middleware'
_10
_10
const withRequestId = defineMiddleware<'requestId', void, Record<never, never>, string>({
_10
key: 'requestId',
_10
run: () => async (req) => ({
_10
requestId: req.headers.get('x-request-id') ?? crypto.randomUUID(),
_10
}),
_10
})

The authoring guide covers prerequisites, the response seam, bundling several middleware into one, and publishing to npm and JSR.

Why we built this#

Per-request logic is stuck where you wrote it. Move to a different runtime and you write it again. Adopt a framework and you rewrite it as that framework's middleware, which cannot leave that framework. Start a second project and you copy the file across. This is the code least worth rewriting: verifying a caller, scoping a database connection to them, handling CORS, checking a flag. It is fiddly, security-sensitive, and easy to get subtly wrong the second time.

@supabase/server has run on this engine since 1.5.1, released on August 31, 2026. withSupabase is a composite of single-key parts: the auth gate, claims, CORS, the Supabase client, the admin client. withOAuthProtectedResource handles the whole OAuth protected-resource flow an MCP client expects, and it is one entry in the pipeline. None of it uses a private API. What you get is the same primitive we use.

Build in a weekend, scale to millions