Skip to content

FAQ ​

Why Fetch API instead of Express-style req/res? ​

The standard Request/Response API is implemented natively by Node 18+, Bun, Deno, and Cloudflare Workers. Building on it means the same code runs everywhere without adapter rewrites. Express's req/res are tied to Node's http module, which is why it needs serverless-http for Lambda and can't run on Workers at all.

Why so many packages instead of one big framework? ​

  1. Tree-shaking — a Cloudflare Worker shouldn't pull in Node's worker_threads or Lambda types.
  2. Dependency isolation — @nodalite/ml's ONNX dep is ~270MB, but it's optional. Apps that don't touch ML pay nothing.
  3. Independent versioning — adapter fixes don't bump core.

Can I use Nodalite with my existing database / ORM? ​

Yes. Nodalite has no built-in database layer. Use Drizzle, Prisma, Kysely, or any other data library directly in your handlers.

Can I use Nodalite with my existing auth system? ​

Yes. The jwtAuth/signJwt middleware is a convenience, not a requirement. You can use Passport.js, Auth0, Clerk, or any custom auth system — just handle it in your own middleware.

How does @nodalite/ml protect against malicious model files? ​

Model enforces three safety checks by default when loading local files or URLs:

  1. Path traversal protection — resolved file paths must stay inside projectRoot (default: process.cwd()).
  2. Size limits — models are capped at 50 MB by default (maxBytes).
  3. Format validation — only .onnx, .bin, and .model extensions are allowed; .onnx files are verified against the ONNX magic bytes.

Override or disable any of these via ModelOptions. See ML Inference for details.

Does Nodalite work with TypeScript? ​

Yes. Every package ships with .d.ts files. The App and Context classes are generic-typed for request-scoped store values.

Does Nodalite work with ESM and CJS? ​

Yes. Every package is dual-published with both import and require entry points via the exports map in package.json.

Is there a WebSocket solution? ​

Yes — @nodalite/ws provides a runtime-agnostic WebSocket server with path-based routing, rooms, heartbeat, and per-connection typed state. It includes adapters for Node.js, Cloudflare Workers, Deno, Bun, and AWS Lambda. On Node.js, it can use the ws library or a zero-dependency RFC 6455 fallback.

What's deliberately NOT included? ​

  • No ORM/database layer — use Drizzle, Prisma, Kysely directly
  • No DI container — c.set/c.get with a Map is sufficient; bring tsyringe or awilix if you need more
  • No file upload handling — use Busboy, formidable, or any multipart library directly

What is the QUERY method? ​

QUERY (RFC 10008) is an HTTP method that is safe and idempotent like GET, but also accepts a request body. It's useful for search or filter operations where the query is too complex for URL parameters:

ts
app.query('/search', async (c) => {
  const { filters, sort, pagination } = await c.req.json();
  const results = await db.search(filters, sort, pagination);
  return c.json({ results });
});

Use QUERY when the operation should never cause side effects but needs a structured body. Use POST when the operation creates or modifies resources.

When should I use auto-discovery? ​

Use discover() when your project has many route files and you want to avoid manually importing each one. It scans a directory, imports every route file, and registers them automatically — subdirectories become route groups with prefix detection via _prefix.ts files.

It's a good fit for medium-to-large APIs with dozens of route files. For small projects with a handful of routes, explicit imports in app.ts are simpler and more transparent.

Auto-discovery uses dynamic import() and works on Node, Bun, and Deno. It's not suitable for bundled edge runtimes (Cloudflare Workers) — use static imports there.

Are the in-memory stores production-ready? ​

No. MemoryRateLimitStore, MemoryApiKeyStore, and MemorySessionStore are single-process only — each instance has its own isolated memory. They're intended for development and testing.

For production, implement the corresponding store interface against a shared datastore:

StoreInterfaceProduction options
Rate limitingRateLimitStoreRedis, Upstash, DynamoDB
API keysApiKeyStoreRedis, Postgres, DynamoDB
SessionsSessionStoreRedis, DynamoDB, Postgres

All memory stores include cleanup timers and destroy() methods to prevent leaks in long-running processes.

Which security middleware do I need? ​

ThreatMiddlewareWhen to use
CSRFcsrf()Browser-facing forms or cookie-based auth
XSS (stored)xssSanitize()User content rendered as HTML later
SSRFssrfGuard()Routes that fetch user-supplied URLs
Brute forcerateLimit()Any public endpoint
Unauthorized accessjwtAuth() or apiKey()Protecting API routes
IP abuseipGuard()Admin panels, geo-restricted APIs
Wrong content typecontentTypeGuard()API endpoints expecting specific payloads
Hanging requestsrequestTimeout()Slow backends, external API calls
Session hijackingsessions()Cookie-based auth (alternative to JWT)
Missing trace contextrequestId()Distributed systems, log correlation

Not every API needs all of them. Start with rateLimit, cors, securityHeaders, and bodyLimit — add the rest as your threat model requires.

Can I contribute? ​

Yes! See CONTRIBUTING.md.

License ​

MIT — see the LICENSE file. Copyright © 2026-present Akkil M G.

Last updated:

Released under the MIT License.