# 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:
```tsx
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.