Works on Workers

Discover which npm packages work in Cloudflare Workers. 395+ packages tested and working.

395+
Packages Working
992
Packages Tested
80
💡 Alternatives

Browse by Category

Showing runtime packages only. Build tools, CLI tools, and test frameworks are hidden by default.

Enable "Show build tools & incompatible" to see all 992 tested packages.

Showing 14 packages

@apidevtools/swagger-parser

⚠️ Works (with notes)
v12.1.0 3,050,382 weekly downloads validation

OpenAPI/Swagger parser. parse() and dereference() work, but validate() fails because it uses ajv internally (code generation). Use for parsing specs, not validation.

View Example
import SwaggerParser from '@apidevtools/swagger-parser';

// Usage: Parse OpenAPI/Swagger specs (validation uses ajv which fails)
const spec = {
  openapi: '3.0.0',
  info: { title: 'My API', version: '1.0.0' },
  paths: { '/users': { get: { responses: { '200': { description: 'OK' } } } } }
};
const parsed = await SwaggerParser.parse(spec);
return { success: true, result: { title: parsed.info.title } };

assert-plus

✅ Works
v1.0.0 19,410,392 weekly downloads validation

Extra assertions on top of Node.js assert module - provides type checking utilities

View Example
import assert from 'assert-plus';

// Usage:
assert.string('hello', 'value');
assert.number(42, 'value');
assert.object({ foo: 'bar' }, 'value');
return { success: true, result: 'All assertions passed' };
v4.2.5 1,297,309 weekly downloads validation

Async form validation library - commonly used with Ant Design forms

View Example
import Schema from 'async-validator';

// Usage:
const descriptor = {
  name: { type: 'string', required: true, message: 'Name is required' },
  age: { type: 'number', min: 0, max: 120 }
};
const validator = new Schema(descriptor);
const result = await validator.validate({ name: 'Alice', age: 30 });
return { success: true, result };

class-validator

⚠️ Works (with notes)
v0.14.3 5,479,996 weekly downloads validation

Decorator-based validation. Decorators require TypeScript with experimentalDecorators and special bundler config. Consider using zod instead for simpler setup.

💡 Alternative: zod

View Example
import { ValidationError } from 'class-validator';

// Usage: Decorators need TypeScript experimentalDecorators
const err = new ValidationError();
err.property = 'email';
err.constraints = { isEmail: 'must be valid email' };
return { success: true, result: { note: 'Use zod for Workers - decorators need special bundler config' } };
v2.0.4 1,119,780 weekly downloads validation

Simple email validation

View Example
import validator from 'email-validator';

// Usage:
const valid = validator.validate('test@example.com');
const invalid = validator.validate('notanemail');
return { success: valid && !invalid, result: { valid, invalid } };

is-url

✅ Works
v1.2.4 7,023,699 weekly downloads validation

Validate if a string is a valid URL

View Example
import isUrl from 'is-url';

// Usage:
const results = [
  isUrl('https://example.com'),
  isUrl('http://example.com/path'),
  isUrl('not a url'),
  isUrl('example.com')
];
return { success: results[0] && results[1] && !results[2] && !results[3], result: results };

joi

✅ Works
v18.0.2 13,183,645 weekly downloads validation

Powerful schema validation with nested objects, arrays, conditionals, custom messages. Works on Workers unlike ajv (which uses new Function).

View Example
import Joi from 'joi';

export default {
  async fetch(request) {
    const userSchema = Joi.object({
      username: Joi.string().alphanum().min(3).max(30).required(),
      email: Joi.string().email().required(),
      age: Joi.number().integer().min(0).max(120),
      role: Joi.string().valid('admin', 'user').default('user')
    });
    
    const body = await request.json();
    const { error, value } = userSchema.validate(body, { abortEarly: false });
    
    if (error) {
      return Response.json({ errors: error.details.map(d => d.message) }, { status: 400 });
    }
    return Response.json({ valid: true, data: value });
  }
};

prop-types

✅ Works
v15.8.1 38,331,118 weekly downloads validation

React PropTypes - runtime type checking for React components

View Example
import PropTypes from 'prop-types';

// Usage:
const stringType = PropTypes.string.isRequired;
const numberType = PropTypes.number;
const objectShape = PropTypes.shape({
  name: PropTypes.string,
  age: PropTypes.number
});
return { 
  success: typeof stringType === 'function' && typeof numberType === 'function',
  result: { hasString: !!stringType, hasNumber: !!numberType, hasShape: !!objectShape }
};

superstruct

✅ Works
v2.0.2 2,973,804 weekly downloads validation

Data validation library

View Example
import { object, string, number } from 'superstruct';

// Usage:
const User = object({ name: string(), age: number() });
try {
  const result = User.create({ name: 'Alice', age: 30 });
  return { success: result.name === 'Alice', result };
} catch (e) {
  return { success: false, result: e.message };
}

valibot

✅ Works
v1.2.0 4,646,764 weekly downloads validation
View Example
import * as v from 'valibot';

// Usage:
const schema = v.object({ name: v.string() });
const result = v.safeParse(schema, { name: 'Alice' });
return { success: result.success, result: result.output };

valid-url

✅ Works
v1.0.9 2,564,044 weekly downloads validation

URL validation

View Example
import validUrl from 'valid-url';

// Usage:
const valid = validUrl.isUri('http://example.com');
const invalid = validUrl.isUri('not a url');
return { success: valid && !invalid, result: { valid, invalid } };

validator

✅ Works
v13.15.26 15,499,361 weekly downloads validation

String validation library

View Example
import validator from 'validator';

// Usage:
const email = validator.isEmail('test@example.com');
const notEmail = validator.isEmail('not-an-email');
return { success: email && !notEmail, result: { email, notEmail } };

yup

✅ Works
v1.7.1 7,907,264 weekly downloads validation
View Example
import * as yup from 'yup';

// Usage:
const schema = yup.object({ name: yup.string().required() });
const result = await schema.validate({ name: 'Alice' });
return { success: true, result };

zod

✅ Works
v4.3.5 67,068,821 weekly downloads validation
View Example
import { z } from 'zod';

// Usage:
const schema = z.object({ name: z.string(), age: z.number() });
const result = schema.safeParse({ name: 'Alice', age: 30 });
return { success: result.success, result: result.data };

Common Questions

Why are so many packages marked "Build/Dev Tool"?

Many popular npm packages are build tools (webpack, babel), test frameworks (jest, mocha), or CLI utilities (chalk, commander) that run during development—not in production. Cloudflare Workers is a runtime environment for production code. These tools still work great for building your Workers project, they just don't run inside Workers themselves.

Can I use Express/Koa/Hapi in Workers?

Yes! As of September 2025, Workers supports node:http server APIs. Use httpServerHandler from cloudflare:node to wrap Express, Koa, or other Node.js HTTP frameworks. For new projects, we recommend lightweight alternatives like Hono or itty-router which are built for edge environments.

What about databases like PostgreSQL or MySQL?

Workers supports database clients like pg (PostgreSQL) and mysql2 when connecting to public endpoints. For production, use edge-optimized solutions: Cloudflare D1 (SQLite), Neon (serverless Postgres), PlanetScale (MySQL), or Upstash Redis.

Why doesn't package X work?

Common reasons: Native modules (C++ bindings like sharp, bcrypt) don't work—use alternatives like bcryptjs or Cloudflare Images. Filesystem access (fs module for local files) isn't available—use KV, R2, or D1 instead. TCP sockets (raw socket.io, redis) aren't supported—use Durable Objects, WebSockets, or HTTP-based alternatives.