From clerk-pack
Optimize Clerk costs and understand pricing. Use when planning budget, reducing costs, or understanding Clerk pricing model. Trigger with phrases like "clerk cost", "clerk pricing", "reduce clerk cost", "clerk billing", "clerk budget".
How this skill is triggered — by the user, by Claude, or both
Slash command
/clerk-pack:clerk-cost-tuningThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Understand Clerk pricing and optimize costs. Clerk charges by Monthly Active Users (MAU). Covers pricing tiers, MAU reduction strategies, caching to reduce API calls, and usage monitoring.
Understand Clerk pricing and optimize costs. Clerk charges by Monthly Active Users (MAU). Covers pricing tiers, MAU reduction strategies, caching to reduce API calls, and usage monitoring.
| Plan | Price | MAU Included | Extra MAU |
|---|---|---|---|
| Free | $0/mo | 10,000 MAU | N/A |
| Pro | $25/mo | 10,000 MAU | $0.02/MAU |
| Enterprise | Custom | Custom | Custom |
Key pricing concepts:
// Strategy 1: Defer authentication — don't force sign-in until necessary
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const requiresAuth = createRouteMatcher([
'/dashboard(.*)',
'/settings(.*)',
'/api/protected(.*)',
])
export default clerkMiddleware(async (auth, req) => {
// Only require auth for specific routes (not entire site)
if (requiresAuth(req)) {
await auth.protect()
}
})
// Strategy 2: Use anonymous access for read-only features
// app/blog/[slug]/page.tsx
import { auth } from '@clerk/nextjs/server'
export default async function BlogPost({ params }: { params: { slug: string } }) {
const { userId } = await auth() // Check but don't require
const post = await db.post.findUnique({ where: { slug: params.slug } })
return (
<article>
<h1>{post?.title}</h1>
<div>{post?.content}</div>
{userId ? <CommentForm /> : <p>Sign in to comment</p>}
</article>
)
}
// lib/user-cache.ts
import { cache } from 'react'
import { currentUser } from '@clerk/nextjs/server'
// Deduplicate within single request (free)
export const getUser = cache(async () => {
return currentUser()
})
// Cross-request caching reduces Backend API calls
import { unstable_cache } from 'next/cache'
import { clerkClient } from '@clerk/nextjs/server'
export const getUserMetadata = unstable_cache(
async (userId: string) => {
const client = await clerkClient()
const user = await client.users.getUser(userId)
return user.publicMetadata
},
['user-metadata'],
{ revalidate: 600 } // 10-minute cache
)
// app/api/admin/clerk-usage/route.ts
import { auth, clerkClient } from '@clerk/nextjs/server'
export async function GET() {
const { has } = await auth()
if (!has({ role: 'org:admin' })) {
return Response.json({ error: 'Admin only' }, { status: 403 })
}
const client = await clerkClient()
const users = await client.users.getUserList({ limit: 1 })
return Response.json({
totalUsers: users.totalCount,
// Estimate MAU based on recent sign-ins
estimatedMAU: 'Check Clerk Dashboard > Billing for actual MAU',
dashboardUrl: 'https://dashboard.clerk.com/last-active?after=30d',
})
}
// scripts/cleanup-inactive-users.ts
import { createClerkClient } from '@clerk/backend'
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
async function findInactiveUsers(daysInactive = 90) {
const cutoff = Date.now() - daysInactive * 24 * 60 * 60 * 1000
const allUsers = await clerk.users.getUserList({ limit: 500 })
const inactive = allUsers.data.filter(
(user) => (user.lastSignInAt || 0) < cutoff
)
console.log(`Found ${inactive.length} users inactive for ${daysInactive}+ days`)
console.log('Consider: notification campaign, data export, or account cleanup')
return inactive
}
findInactiveUsers()
| Issue | Cause | Solution |
|---|---|---|
| Unexpected bill increase | MAU spike from bot traffic | Add bot detection, restrict auth to needed routes |
| Feature limitations | Free tier limits (no SSO, etc.) | Upgrade to Pro ($25/mo) |
| High API call volume | No caching | Add React cache() + unstable_cache() |
| MAU count mismatch | Counting test users | Use separate dev instance (free, unlimited) |
function estimateMonthlyCost(mau: number): string {
if (mau <= 10_000) return 'Free tier ($0/mo)'
const overage = mau - 10_000
const cost = 25 + overage * 0.02
return `Pro tier: $${cost.toFixed(2)}/mo (${overage.toLocaleString()} extra MAU at $0.02 each)`
}
console.log(estimateMonthlyCost(15_000)) // "Pro tier: $125.00/mo (5,000 extra MAU at $0.02 each)"
console.log(estimateMonthlyCost(50_000)) // "Pro tier: $825.00/mo (40,000 extra MAU at $0.02 each)"
Proceed to clerk-reference-architecture for architecture patterns.
npx claudepluginhub flight505/skill-forge --plugin clerk-packProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.