The WorkOS SDK provides a specialized build optimized for edge worker environments like Cloudflare Workers, Vercel Edge Functions, and Convex.
The SDK automatically detects and optimizes for these edge platforms:
Cloudflare Workers Serverless JavaScript execution at the edge
Vercel Edge Functions Edge middleware and API routes
Convex Backend platform with edge functions
Automatic Runtime Detection
The SDK uses conditional exports to automatically load the worker build:
{
"exports": {
".": {
"workerd": "./lib/index.worker.js", // Cloudflare Workers
"edge-light": "./lib/index.worker.js", // Vercel Edge
"convex": "./lib/index.worker.js" // Convex
}
}
}
You don’t need to configure anything - just import normally:
import { WorkOS } from '@workos-inc/node' ;
// Automatically uses index.worker.js in edge environments
Worker Build Differences
The worker build (index.worker.js) is optimized for edge constraints:
Uses only Web Standards APIs (no Node.js APIs):
fetch() instead of Node.js http
SubtleCrypto for cryptographic operations
console.warn() instead of process.emitWarning()
Warnings use console.warn() instead of process.emitWarning(): emitWarning(warning: string): void {
return console.warn(`WorkOS: ${warning}`);
}
Cloudflare Workers
Installation
npm install @workos-inc/node
Basic Example
import { WorkOS } from '@workos-inc/node' ;
export default {
async fetch ( request : Request , env : Env ) : Promise < Response > {
const workos = new WorkOS ( env . WORKOS_API_KEY );
try {
const { data : users } = await workos . userManagement . listUsers ();
return Response . json ( users );
} catch ( error ) {
return Response . json (
{ error: error . message },
{ status: 500 }
);
}
} ,
} ;
Environment Variables
Store your API key in Cloudflare Workers secrets:
wrangler secret put WORKOS_API_KEY
Then access it via the env parameter:
interface Env {
WORKOS_API_KEY : string ;
}
export default {
async fetch ( request : Request , env : Env ) : Promise < Response > {
const workos = new WorkOS ( env . WORKOS_API_KEY );
// ...
} ,
} ;
Webhook Verification
import { WorkOS } from '@workos-inc/node' ;
export default {
async fetch ( request : Request , env : Env ) : Promise < Response > {
const workos = new WorkOS ( env . WORKOS_API_KEY );
const payload = await request . text ();
const signature = request . headers . get ( 'workos-signature' );
try {
const webhook = await workos . webhooks . constructEvent ({
payload ,
sigHeader: signature ,
secret: env . WORKOS_WEBHOOK_SECRET ,
});
console . log ( 'Webhook event:' , webhook . event );
return Response . json ({ received: true });
} catch ( error ) {
return Response . json (
{ error: 'Invalid signature' },
{ status: 400 }
);
}
} ,
} ;
wrangler.toml Configuration
name = "workos-worker"
main = "src/worker.ts"
compatibility_date = "2024-01-01"
[ vars ]
WORKOS_CLIENT_ID = "client_123"
# Use secrets for sensitive values:
# wrangler secret put WORKOS_API_KEY
# wrangler secret put WORKOS_WEBHOOK_SECRET
Vercel Edge Functions
Installation
npm install @workos-inc/node
Edge API Route
import { WorkOS } from '@workos-inc/node' ;
import { NextResponse } from 'next/server' ;
// Force this route to use Edge Runtime
export const runtime = 'edge' ;
const workos = new WorkOS ( process . env . WORKOS_API_KEY );
export async function GET () {
try {
const { data : users } = await workos . userManagement . listUsers ();
return NextResponse . json ( users );
} catch ( error ) {
return NextResponse . json (
{ error: error . message },
{ status: 500 }
);
}
}
Edge Middleware
import { WorkOS } from '@workos-inc/node' ;
import { NextRequest , NextResponse } from 'next/server' ;
export const config = {
matcher: '/api/:path*' ,
};
const workos = new WorkOS ( process . env . WORKOS_API_KEY );
export async function middleware ( request : NextRequest ) {
const token = request . cookies . get ( 'session' )?. value ;
if ( ! token ) {
return NextResponse . redirect ( new URL ( '/login' , request . url ));
}
try {
// Verify session token
const session = await workos . userManagement . authenticateWithRefreshToken ({
refreshToken: token ,
clientId: process . env . WORKOS_CLIENT_ID ! ,
});
const response = NextResponse . next ();
response . headers . set ( 'X-User-Id' , session . user . id );
return response ;
} catch ( error ) {
return NextResponse . redirect ( new URL ( '/login' , request . url ));
}
}
Environment Variables
WORKOS_API_KEY = sk_test_1234567890
WORKOS_CLIENT_ID = client_1234567890
Convex
Installation
npm install @workos-inc/node
Convex Function
import { query } from './_generated/server' ;
import { WorkOS } from '@workos-inc/node' ;
const workos = new WorkOS ( process . env . WORKOS_API_KEY );
export const listUsers = query ( async () => {
const { data : users } = await workos . userManagement . listUsers ();
return users ;
});
Environment Variables
Set environment variables in the Convex dashboard or via CLI:
npx convex env set WORKOS_API_KEY sk_test_1234567890
Testing Edge Functions
Cloudflare Workers (Miniflare)
import { unstable_dev } from 'wrangler' ;
import { describe , it , expect , beforeAll , afterAll } from 'vitest' ;
describe ( 'Worker' , () => {
let worker ;
beforeAll ( async () => {
worker = await unstable_dev ( 'src/worker.ts' , {
experimental: { disableExperimentalWarning: true },
});
});
afterAll ( async () => {
await worker . stop ();
});
it ( 'lists users' , async () => {
const resp = await worker . fetch ( '/users' );
expect ( resp . status ). toBe ( 200 );
const users = await resp . json ();
expect ( Array . isArray ( users )). toBe ( true );
});
});
Vercel Edge Functions (Next.js)
app/api/users/route.test.ts
import { GET } from './route' ;
import { NextRequest } from 'next/server' ;
jest . mock ( '@workos-inc/node' );
it ( 'returns users' , async () => {
const request = new NextRequest ( 'http://localhost:3000/api/users' );
const response = await GET ( request );
expect ( response . status ). toBe ( 200 );
const data = await response . json ();
expect ( Array . isArray ( data )). toBe ( true );
});
Limitations
Edge runtimes have several constraints compared to Node.js:
You cannot use Node.js-specific modules like fs, path, or crypto (use SubtleCrypto instead).
Most edge platforms have CPU time limits (typically 50ms for Cloudflare Workers free tier, 10-30 seconds for paid tiers).
Edge workers typically have 128MB RAM limits. The WorkOS SDK is lightweight but be mindful of response sizes.
First requests may be slower due to cold starts. Keep initialization code minimal.
Initialize outside handlers
Create the WorkOS instance outside your handler function to reuse across requests: // Good: Reused across requests
const workos = new WorkOS ( env . WORKOS_API_KEY );
export default {
async fetch ( request : Request , env : Env ) {
// Use workos here
}
}
Use streaming for large responses
When dealing with large datasets, use pagination: const { data : users , listMetadata } =
await workos . userManagement . listUsers ({
limit: 10 ,
});
// Fetch next page if needed
if ( listMetadata . after ) {
const nextPage = await workos . userManagement . listUsers ({
after: listMetadata . after ,
limit: 10 ,
});
}
Cache responses when possible
Use edge caching for frequently accessed data: const cacheKey = `users- ${ organizationId } ` ;
const cached = await cache . get ( cacheKey );
if ( cached ) return cached ;
const { data : users } = await workos . userManagement . listUsers ({
organizationId ,
});
await cache . put ( cacheKey , users , { expirationTtl: 300 });
return users ;
Next Steps
User Management Manage users at the edge
Webhooks Verify webhooks in edge functions
Node.js Runtime Compare with standard Node.js usage
Performance Optimize edge function performance