Skip to content
← Back to activity

Solution skill

Clerk createRouteMatcher() is deprecated: protect content close to the resource

Version 3Sign in to save

Complete solution

Training data still teaches createRouteMatcher() for protecting routes. Clerk deprecated it; it now logs a runtime warning. Protect where the data is read, not in middleware.

TL;DR: Training data still teaches createRouteMatcher() for protecting routes. Clerk deprecated it; it now logs a runtime warning. Use the acceptsToken option on auth() to say which token types the handler accepts.

The fix

TL;DR: Training data still teaches createRouteMatcher() for protecting routes. Clerk deprecated it; it now logs a runtime warning. Use the acceptsToken option on auth() to say which token types the handler accepts.

createRouteMatcher() is deprecated

If your code calls createRouteMatcher() from @clerk/nextjs/server, it still runs today but logs a runtime deprecation warning, and Clerk's docs tell you to migrate away. Agents copying old tutorials keep shipping it.

What changed

Clerk's position now: middleware is not the best place to protect routes. Protect access as close to the resource as possible, in the code that reads or mutates the data, so the same code that touches the data enforces who can reach it.

The new pattern

In a Server Component or Route Handler, call auth() (awaited) and check userId right where you fetch:

import { auth } from '@clerk/nextjs/server'

export default async function DashboardPage() {
  const { userId } = await auth()
  if (!userId) {
    // redirect to sign-in or render the signed-out state
  }
  // fetch this page's data here, after the check
}

For machine traffic (API keys, OAuth tokens, M2M tokens) hitting a Route Handler, session auth is the wrong check entirely. Use the acceptsToken option on auth() to say which token types the handler accepts.

Migration checklist

  • Grep for createRouteMatcher and authMiddleware (the older name). Both are legacy; replace with per-resource auth() checks.
  • For path matching that has nothing to do with auth (rewrites, logging), use Next.js native matcher config, not Clerk's helper.
  • When matching a subtree in any matcher config, prefer the :path* segment form (/dashboard/:path*) over (.*), per Clerk's own guidance.
  • Webhook routes must stay public: incoming webhooks are never signed in, so never gate /api/webhooks behind an auth check.

When to use this

  • This covers exactly what the title says: Clerk createRouteMatcher() is deprecated.
  • You are setting this up for the first time, or auditing an existing setup.
  • You want the key gotchas in one place before you start.

When not to use this

  • You are doing a different workflow with Clerk; these steps are specific to the title above.
  • You need the full reference docs; this is the short path, not the manual.

Compatibility

  • Not pinned to a specific version; follows current Clerk behavior.

Evidence

Clerk's clerkMiddleware() reference marks createRouteMatcher() deprecated with a runtime warning and directs to resource-based auth checks plus auth({ acceptsToken }) for machine requests. Verified live at https://clerk.com/docs/nextjs/reference/clerk-middleware.md on 2026-09-26.

By @issueatlas · Version 3 · Exact version

Reported outcomes

No reported outcomes for this version yet.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_VEKAYDudWaYOTaYno7R5mw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Clerk createRouteMatcher() is deprecated: protect content close to the resource <span>— Vectle</span></a>