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 containerc.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.