- Blazing Fast - Radix tree-based router with performance optimizations
- Zero Dependencies - Built entirely with Node.js built-in modules
- Advanced Routing - Dynamic parameters, wildcards, and pattern matching
- WebSocket Support - Full WebSocket implementation with rooms and broadcasting
- Middleware System - Express-style middleware with async support
- Template Engines - Built-in template engine support with caching
- Security Features - CORS, rate limiting, session management, and validation
- Performance Monitoring - Built-in performance tracking and optimization
- Compression - Gzip, deflate, and brotli compression support
- Cookie Management - Cookie parsing and signing capabilities
Velocy is 5.56x faster than Express based on our latest benchmarks:
| Framework | Req/Sec | Avg Latency | Transfer Rate |
|---|---|---|---|
| Velocy | 91,330 | 1.40ms | 16.11 MB/s |
| Express | 16,438 | 7.78ms | 3.76 MB/s |
- 5.56x more requests per second
- 5.56x lower average latency
- 4.28x higher transfer rate
- Zero dependencies for maximum efficiency
Benchmarked using rewrk with 128 connections on Node.js v20.x LTS
npm install velocy # or yarn add velocy # or pnpm add velocyconst { Router, createServer } = require("velocy"); const app = new Router(); // Basic route app.get("/", (req, res) => { res.json({ message: "Hello, Velocy!" }); }); // Dynamic parameters app.get("/users/:id", (req, res) => { res.json({ userId: req.params.id }); }); // Start server createServer(app).listen(3000, () => { console.log("Server running on http://localhost:3000"); });Velocy includes a fully-functional server implementations to help you get started:
A comprehensive reference implementation showcasing everything Velocy can do:
- ALL framework features demonstrated
- Every HTTP method, router type, and middleware pattern
- Advanced WebSocket with rooms
- View engine integration
- Performance monitoring
- Extensive inline documentation
Run it: node example_server.js
- Routing
- Middleware
- Request & Response
- WebSockets
- Template Engines
- Static Files
- Body Parsing
- Cookies
- Sessions
- CORS
- Compression
- Rate Limiting
- Validation
- Performance Optimization
- API Reference
const { Router } = require("velocy"); const app = new Router(); // HTTP methods app.get("/users", (req, res) => res.json({ users: [] })); app.post("/users", (req, res) => res.json({ created: true })); app.put("/users/:id", (req, res) => res.json({ updated: req.params.id })); app.delete("/users/:id", (req, res) => res.json({ deleted: req.params.id })); app.patch("/users/:id", (req, res) => res.json({ patched: req.params.id })); // Route chaining app.get("/posts", listPosts).post("/posts", createPost).get("/posts/:id", getPost);// Single parameter app.get("/users/:id", (req, res) => { res.json({ userId: req.params.id }); }); // Multiple parameters app.get("/users/:userId/posts/:postId", (req, res) => { res.json({ userId: req.params.userId, postId: req.params.postId, }); }); // Optional parameters with wildcards app.get("/files/*", (req, res) => { res.json({ file: req.params["*"] }); });// Single-segment wildcard (*) app.get("/static/*.js", (req, res) => { res.json({ jsFile: req.params["*"] }); }); // Multi-segment wildcard (**) app.get("/api/**", (req, res) => { res.json({ path: req.params["**"] }); }); // Named wildcards app.get("/assets/*filename", (req, res) => { res.json({ filename: req.params.filename }); });// Create modular routers const userRouter = new Router(); userRouter.get("/profile", getUserProfile); userRouter.post("/settings", updateSettings); const apiRouter = new Router(); apiRouter.get("/status", getApiStatus); // Merge routers const mainRouter = new Router(); mainRouter.merge(userRouter); mainRouter.merge(apiRouter); // Nest routers with prefix const app = new Router(); app.nest("/api/v1", mainRouter); // Routes available at: /api/v1/profile, /api/v1/settings, /api/v1/status// Print the route tree for debugging app.printTree(); // Outputs a visual representation of all registered routesconst { Router, bodyParser, cookieParser } = require("velocy"); const app = new Router(); // Apply middleware globally app.use(cookieParser()); app.use(bodyParser.json()); // Custom middleware app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); }); // Async middleware app.use(async (req, res, next) => { await authenticateUser(req); next(); });// Apply middleware to specific paths app.use("/admin", authenticateAdmin); app.use("/api", rateLimiter); // Multiple middleware app.use("/protected", [authenticate, authorize, logAccess]);// Error middleware (4 parameters) app.use((err, req, res, next) => { console.error(err.stack); res.status(err.statusCode || 500).json({ error: err.message || "Internal Server Error", }); });app.get("/example", (req, res) => { // URL and query parsing console.log(req.url); // Full URL console.log(req.path); // Path without query console.log(req.query); // Parsed query parameters // Headers console.log(req.headers); // All headers console.log(req.get("content-type")); // Get specific header // Content negotiation console.log(req.accepts("json")); // Check if client accepts JSON console.log(req.acceptsEncodings(["gzip", "deflate"])); console.log(req.acceptsLanguages(["en", "es"])); // Request info console.log(req.ip); // Client IP console.log(req.protocol); // http or https console.log(req.secure); // Is HTTPS? console.log(req.xhr); // Is AJAX request? // Cookies (with cookieParser middleware) console.log(req.cookies); // Parsed cookies console.log(req.signedCookies); // Signed cookies });app.get("/example", (req, res) => { // JSON response res.json({ success: true }); // Status codes res.status(201).json({ created: true }); // Redirects res.redirect("/new-location"); res.redirect(301, "/permanent-redirect"); // Headers res.set("X-Custom-Header", "value"); res.set({ "X-Header-1": "value1", "X-Header-2": "value2", }); // Cookies res.cookie("session", "abc123", { maxAge: 900000, httpOnly: true, secure: true, sameSite: "strict", }); // File sending res.sendFile("/path/to/file.pdf"); res.download("/path/to/file.pdf", "custom-name.pdf"); // Content type res.type("html").send("<h1>Hello</h1>"); res.type("text/plain").send("Plain text"); });const { Router, createServer } = require("velocy"); const app = new Router({ websocket: { heartbeatInterval: 30000, // Ping every 30 seconds heartbeatTimeout: 60000, // Close if no pong in 60 seconds maxPayloadSize: 10 * 1024 * 1024, // 10MB max message size enableQueue: true, // Queue messages for offline clients maxQueueSize: 100, // Max queued messages per client }, }); // WebSocket routes app.ws("/chat", (ws, req) => { console.log("New WebSocket connection"); ws.on("message", (data) => { // Echo message back ws.send(JSON.stringify({ echo: data })); }); ws.on("close", () => { console.log("Connection closed"); }); }); createServer(app).listen(3000);// Join/leave rooms app.ws("/chat", (ws, req) => { // Join a room ws.join("general"); ws.on("message", (data) => { const msg = JSON.parse(data); if (msg.type === "join") { ws.join(msg.room); ws.send(JSON.stringify({ joined: msg.room })); } if (msg.type === "leave") { ws.leave(msg.room); ws.send(JSON.stringify({ left: msg.room })); } if (msg.type === "broadcast") { // Broadcast to all in room app.wsRouter.broadcast( msg.room, JSON.stringify({ from: ws.id, message: msg.text, }), ); } }); }); // Broadcast to all connected clients app.wsRouter.broadcastAll(JSON.stringify({ announcement: "Server message" })); // Get room information const roomClients = app.wsRouter.getRoom("general"); const allRooms = app.wsRouter.getRooms();const { Router, createServer } = require("velocy"); const app = new Router(); // Configure views app.set("views", "./views"); app.set("view engine", "html"); app.set("view cache", true); // Enable caching in production // Render templates app.get("/", (req, res) => { res.render("index", { title: "Velocy App", user: { name: "John" }, }); }); // With layout app.get("/about", (req, res) => { res.render("about", { title: "About Us", layout: "layouts/main", }); });// Register a custom engine app.engine("ejs", { compile: (template, options) => { // Return compiled function return (locals) => { // Render template with locals return renderedHtml; }; }, }); // Use the custom engine app.set("view engine", "ejs");const { Router, static: staticMiddleware } = require("velocy"); const app = new Router(); // Serve static files from 'public' directory app.use( "/static", staticMiddleware("./public", { index: "index.html", // Default file dotfiles: "ignore", // How to handle dotfiles etag: true, // Enable ETags lastModified: true, // Send Last-Modified header maxAge: "1d", // Cache control max-age immutable: true, // Add immutable directive fallthrough: true, // Pass to next middleware if not found acceptRanges: true, // Enable range requests cacheControl: true, // Send Cache-Control header // Custom headers setHeaders: (res, path, stat) => { if (path.endsWith(".pdf")) { res.set("Content-Disposition", "attachment"); } }, }), ); // Multiple static directories app.use("/assets", staticMiddleware("./assets")); app.use("/downloads", staticMiddleware("./files"));const { Router, bodyParser } = require("velocy"); const app = new Router(); // Parse JSON bodies app.use( bodyParser.json({ limit: "10mb", // Size limit strict: true, // Only accept arrays and objects reviver: null, // JSON.parse reviver function type: "application/json", // Content-type to parse }), ); // Parse URL-encoded bodies app.use( bodyParser.urlencoded({ extended: true, // Use querystring library limit: "10mb", // Size limit parameterLimit: 1000, // Max number of parameters type: "application/x-www-form-urlencoded", }), ); // Access parsed body app.post("/users", (req, res) => { console.log(req.body); // Parsed body res.json({ received: req.body }); });// Parse multipart form data app.use( bodyParser.multipart({ uploadDir: "./uploads", // Directory for file uploads keepExtensions: true, // Keep file extensions maxFileSize: 10 * 1024 * 1024, // 10MB max file size maxFields: 1000, // Max number of fields maxFieldsSize: 20 * 1024 * 1024, // 20MB max for all fields hash: "md5", // Calculate file hash multiples: true, // Parse multiple files // File filter fileFilter: (part) => { // Only accept images return part.mimetype.startsWith("image/"); }, }), ); // Handle file uploads app.post("/upload", (req, res) => { console.log(req.body); // Form fields console.log(req.files); // Uploaded files res.json({ fields: req.body, files: req.files, }); });// Parse raw body app.use( bodyParser.raw({ type: "application/octet-stream", limit: "10mb", }), ); // Parse text body app.use( bodyParser.text({ type: "text/plain", defaultCharset: "utf-8", limit: "1mb", }), );const { Router, cookieParser } = require("velocy"); const app = new Router(); // Enable cookie parsing with optional secret for signed cookies app.use(cookieParser("optional-secret-key")); // Read cookies app.get("/cookies", (req, res) => { console.log(req.cookies); // Regular cookies console.log(req.signedCookies); // Signed cookies res.json({ cookies: req.cookies, signed: req.signedCookies, }); }); // Set cookies app.get("/set-cookie", (req, res) => { // Simple cookie res.cookie("name", "value"); // Cookie with options res.cookie("session", "abc123", { domain: ".example.com", // Cookie domain path: "/", // Cookie path secure: true, // HTTPS only httpOnly: true, // Not accessible via JavaScript maxAge: 900000, // Max age in milliseconds expires: new Date(Date.now() + 900000), // Expiration date sameSite: "strict", // CSRF protection signed: true, // Sign the cookie }); res.json({ set: true }); }); // Clear cookies app.get("/clear-cookie", (req, res) => { res.clearCookie("name"); res.clearCookie("session", { path: "/" }); res.json({ cleared: true }); });const { Router, session } = require("velocy"); const app = new Router(); // Configure sessions app.use( session({ secret: "keyboard-cat", // Secret for signing session ID resave: false, // Don't save unchanged sessions saveUninitialized: false, // Don't create empty sessions rolling: true, // Reset expiry on activity cookie: { secure: true, // HTTPS only httpOnly: true, // Not accessible via JavaScript maxAge: 1000 * 60 * 60, // 1 hour sameSite: "strict", // CSRF protection }, name: "sessionId", // Cookie name genid: () => generateId(), // Custom ID generator store: new MemoryStore({ // Session store (default: memory) checkPeriod: 86400000, // Prune expired entries every 24h }), }), ); // Use sessions app.get("/login", (req, res) => { req.session.userId = 123; req.session.username = "john"; res.json({ logged_in: true }); }); app.get("/profile", (req, res) => { if (!req.session.userId) { return res.status(401).json({ error: "Not logged in" }); } res.json({ userId: req.session.userId, username: req.session.username, }); }); app.get("/logout", (req, res) => { req.session.destroy((err) => { if (err) { return res.status(500).json({ error: "Could not log out" }); } res.json({ logged_out: true }); }); });const { Router, cors } = require("velocy"); const app = new Router(); // Enable CORS with default settings app.use(cors()); // Custom CORS configuration app.use( cors({ origin: "https://example.com", // Allowed origin // or multiple origins origin: ["https://example.com", "https://app.example.com"], // or dynamic origin origin: (origin, callback) => { if (isAllowed(origin)) { callback(null, true); } else { callback(new Error("Not allowed by CORS")); } }, methods: ["GET", "POST", "PUT", "DELETE"], // Allowed methods allowedHeaders: ["Content-Type", "Authorization"], // Allowed headers exposedHeaders: ["Content-Length", "X-Token"], // Headers exposed to client credentials: true, // Allow credentials maxAge: 86400, // Preflight cache duration preflightContinue: false, // Pass preflight to next handler optionsSuccessStatus: 204, // Status for successful OPTIONS }), ); // CORS for specific routes app.get("/api/public", cors(), handler); // Different CORS per route const corsOptions = { origin: "https://trusted.com", credentials: true, }; app.get("/api/private", cors(corsOptions), handler);const { Router, compression } = require("velocy"); const app = new Router(); // Enable compression with default settings app.use(compression()); // Custom compression configuration app.use( compression({ threshold: 1024, // Min size to compress (bytes) level: 6, // Compression level (0-9) memLevel: 8, // Memory level (1-9) strategy: 0, // Compression strategy chunkSize: 16384, // Chunk size windowBits: 15, // Window bits filter: (req, res) => { // Custom logic to determine if response should be compressed if (req.headers["x-no-compression"]) { return false; } return compression.filter(req, res); }, // Brotli options brotli: { enabled: true, quality: 4, // Brotli quality (0-11) lgwin: 22, // Brotli window size }, }), );const { Router, rateLimit } = require("velocy"); const app = new Router(); // Basic rate limiting app.use( rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // Max 100 requests per window message: "Too many requests", // Error message statusCode: 429, // Error status code headers: true, // Send rate limit headers skipSuccessfulRequests: false, // Count all requests skipFailedRequests: false, // Count failed requests // Custom key generator keyGenerator: (req) => { return req.ip; // Default: use IP address }, // Custom handler handler: (req, res) => { res.status(429).json({ error: "Too many requests", retryAfter: req.rateLimit.resetTime, }); }, // Skip certain requests skip: (req) => { return req.ip === "127.0.0.1"; }, }), ); // Different limits for different routes const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100, }); const authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5, skipSuccessfulRequests: true, }); app.use("/api", apiLimiter); app.use("/auth/login", authLimiter);const { Router, validator } = require("velocy"); const app = new Router(); // Validate request body app.post( "/users", validator.body({ username: { type: "string", required: true, minLength: 3, maxLength: 20, pattern: /^[a-zA-Z0-9_]+$/, }, email: { type: "string", required: true, format: "email", }, age: { type: "number", min: 18, max: 120, }, roles: { type: "array", items: { type: "string", enum: ["user", "admin", "moderator"], }, }, }), (req, res) => { // Request body is validated res.json({ user: req.body }); }, ); // Validate query parameters app.get( "/search", validator.query({ q: { type: "string", required: true, minLength: 1, }, limit: { type: "number", default: 10, min: 1, max: 100, }, offset: { type: "number", default: 0, min: 0, }, }), (req, res) => { res.json({ results: [] }); }, ); // Validate route parameters app.get( "/users/:id", validator.params({ id: { type: "string", pattern: /^[0-9a-f]{24}$/, // MongoDB ObjectId }, }), (req, res) => { res.json({ userId: req.params.id }); }, ); // Custom validation app.post( "/register", validator.custom(async (req) => { if (req.body.password !== req.body.confirmPassword) { throw new Error("Passwords do not match"); } const userExists = await checkUserExists(req.body.email); if (userExists) { throw new Error("Email already registered"); } return true; }), (req, res) => { res.json({ registered: true }); }, ); // Sanitization app.post( "/comment", validator.body({ text: { type: "string", required: true, sanitize: { trim: true, escape: true, lowercase: false, }, }, }), (req, res) => { res.json({ comment: req.body.text }); }, );const { Router } = require("velocy"); // Create router with performance optimizations const app = new Router({ // Caching cache: true, // Enable route caching routeCacheSize: 1000, // Cache up to 1000 routes urlCacheSize: 500, // Cache up to 500 parsed URLs // Performance monitoring performance: { enabled: true, // Enable performance tracking windowSize: 60000, // 1-minute window for metrics }, // Object pooling enablePooling: true, // Enable object pooling poolSize: 100, // Pool size for reusable objects // Other optimizations trustProxy: true, // Trust proxy headers mergeParams: true, // Merge params from parent router }); // Monitor performance app.on("performance", (metrics) => { console.log("Requests/sec:", metrics.requestsPerSecond); console.log("Avg response time:", metrics.avgResponseTime); console.log("Cache hit rate:", metrics.cacheHitRate); }); // Performance hooks app.hook("beforeRoute", (req) => { req.startTime = Date.now(); }); app.hook("afterRoute", (req, res) => { const duration = Date.now() - req.startTime; res.set("X-Response-Time", `${duration}ms`); });// Run benchmarks const { benchmark } = require("velocy/benchmark"); benchmark({ routes: app, requests: 10000, concurrent: 100, warmup: 1000, }).then((results) => { console.log("Throughput:", results.throughput); console.log("Latency p50:", results.latency.p50); console.log("Latency p99:", results.latency.p99); });class Router { // HTTP methods get(path, ...handlers) post(path, ...handlers) put(path, ...handlers) delete(path, ...handlers) patch(path, ...handlers) head(path, ...handlers) options(path, ...handlers) all(path, ...handlers) // Middleware use(...middleware) use(path, ...middleware) // Router composition merge(router) nest(prefix, router) // WebSocket ws(path, handler) // Settings set(setting, value) get(setting) enable(setting) disable(setting) enabled(setting) disabled(setting) // Template engines engine(ext, engine) render(view, locals, callback) // Events on(event, handler) off(event, handler) emit(event, ...args) // Utilities printTree() getRoutes() clearCache() }interface Request { // Properties app: Router baseUrl: string body: any cookies: object fresh: boolean hostname: string ip: string ips: string[] method: string originalUrl: string params: object path: string protocol: string query: object route: object secure: boolean signedCookies: object stale: boolean subdomains: string[] xhr: boolean // Methods accepts(types: string|string[]): string|false acceptsCharsets(charsets: string|string[]): string|false acceptsEncodings(encodings: string|string[]): string|false acceptsLanguages(languages: string|string[]): string|false get(header: string): string is(type: string|string[]): string|false range(size: number): object|number|string }interface Response { // Properties app: Router headersSent: boolean locals: object statusCode: number statusMessage: string // Methods append(header: string, value: string|string[]): Response attachment(filename?: string): Response clearCookie(name: string, options?: object): Response contentType(type: string): Response cookie(name: string, value: any, options?: object): Response download(path: string, filename?: string, callback?: Function): void end(data?: any, encoding?: string): void format(object: object): Response get(header: string): string json(object: any): Response jsonp(object: any): Response links(links: object): Response location(url: string): Response redirect(status?: number, url?: string): void render(view: string, locals?: object, callback?: Function): void send(body: any): Response sendFile(path: string, options?: object, callback?: Function): void sendStatus(statusCode: number): Response set(header: string|object, value?: string): Response status(statusCode: number): Response type(type: string): Response vary(header: string): Response }const { Router, createServer, bodyParser, cookieParser, session, cors, compression, rateLimit, static: staticMiddleware, } = require("velocy"); // Create app with optimizations const app = new Router({ cache: true, performance: true, }); // Global middleware app.use(compression()); app.use(cors()); app.use(cookieParser("secret")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use( session({ secret: "keyboard cat", resave: false, saveUninitialized: false, }), ); // Rate limiting app.use( "/api", rateLimit({ windowMs: 15 * 60 * 1000, max: 100, }), ); // Static files app.use("/public", staticMiddleware("./public")); // View engine app.set("views", "./views"); app.set("view engine", "html"); // Routes app.get("/", (req, res) => { res.render("index", { title: "Home" }); }); app.get("/api/users", (req, res) => { res.json({ users: [] }); }); app.post("/api/users", (req, res) => { // Create user res.status(201).json({ created: true }); }); // WebSocket app.ws("/ws", (ws, req) => { ws.on("message", (msg) => { ws.send(`Echo: ${msg}`); }); }); // Error handling app.use((err, req, res, next) => { res.status(500).json({ error: err.message }); }); // Start server const server = createServer(app); server.listen(3000, () => { console.log("Server running on http://localhost:3000"); });Contributions are welcome! Please feel free to submit a Pull Request.
MIT © Ishtmeet Singh
- Email: hello@thenodebook.com
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ by Ishtmeet
