Search docs

Jump between documentation pages.

Where to use DaloyJS

DaloyJS is a contract-first TypeScript web framework. It takes an HTTP Request and returns a Response, with validation, OpenAPI, security, and a typed client all wired in. That description fits a lot of jobs, and a few it doesn't. This page is the beginner's map.

If you only read one thing: DaloyJS is excellent at the "your code answers an HTTP request" role , API server, microservice, BFF, webhook receiver, WebSocket server, MCP server. It is nota router that proxies traffic to other services, a load balancer, or a page-rendering UI framework. For those, pair it with something purpose-built and let DaloyJS be the smart endpoint behind them.

The quick verdict

For each role, here is the short answer.

RoleFitIn one sentence
API serverExcellentThis is the home position.
Web server (HTML, static files)Works, but not the pointIt can return HTML, but a CDN or Next.js is better at it.
Microservice (one of many)ExcellentUse the internal-service preset behind a mesh.
Backend-for-Frontend (BFF)ExcellentTyped upstream client + fetchGuard + sessions = exactly the BFF kit.
API gateway (in-app)StrongAll the edge concerns, auth, rate limit, CORS, headers, minus traffic proxying.
API gateway (standalone, fronting many services)Not the right toolUse Kong, APISIX, Envoy, or Tyk.
Load balancerNoUse a real LB (NGINX, HAProxy, ALB, Cloudflare).
Server-side renderer (SSR)NoNo JSX/hydration engine. Use Next.js / Remix / Astro and put DaloyJS behind it.
Webhook receiverExcellentFirst-party HMAC verifier and signed-payload helpers.
WebSocket serverExcellentFirst-party app.ws() with CSWSH refuse-to-boot.
MCP server (HTTP transport)StrongJSON-RPC over HTTP/SSE, DaloyJS handles it; the MCP framing is yours.
gRPC serverNoDaloyJS is HTTP/1.1+HTTP/2 REST. Use @grpc/grpc-js.
GraphQL serverPossible, not nativeYou can mount Yoga/Apollo as a single route, but DaloyJS isn't a GraphQL framework.
SOAP serverNoSOAP is XML/WSDL; DaloyJS speaks JSON contracts.

Plain-English definitions

Before we go role-by-role, here is what each term actually means. If you've been nodding along in meetings without being sure, this is for you.

  • API server: a process that exposes endpoints (likeGET /books/:id) over HTTP and returns structured data (usually JSON). The thing your mobile app, web app, or another service talks to.
  • Web server: historically, a process that serves HTML pages, images, and static files to a browser. NGINX and Apache are web servers. An API server is a specialized web server.
  • Microservice: one small service that does one thing (orders, payments, search) and talks to others over the network. "Microservice architecture" just means you have many of them instead of one big app.
  • Service-to-service (S2S): when two of your own backend services call each other directly, with no human in the loop. Usually authenticated with a shared secret or mTLS, not a user cookie.
  • Backend-for-Frontend (BFF): a thin server that sits between a specific frontend (your web app, your iOS app) and your internal APIs. It composes upstream calls, holds the session, and returns exactly the shape the UI needs.
  • API gateway: a process at the edge of your network that takes all incoming traffic and routes it to the right internal service. It usually handles auth, rate limiting, request translation, retries, and observability for many services at once.
  • Load balancer: a network-level box that takes one stream of requests and spreads them across many identical copies of your service. It cares about TCP connections and health checks, not your routes or schemas.
  • Server-side renderer (SSR): a process that turns components (React, Vue, Svelte) into HTML on the server, then ships that HTML to the browser. Next.js, Remix, and Astro are SSR frameworks.
  • Webhook receiver: an endpoint that other systems (Stripe, GitHub, Shopify) call to notify your app of events. Usually signed with HMAC so you can verify the sender.
  • WebSocket server: a long-lived, bidirectional connection over TCP. Used for chat, live dashboards, multiplayer, collaborative editing.
  • MCP server: Model Context Protocol. A standardized way for AI assistants to call tools and read resources. Transports are stdio or HTTP+SSE.
  • gRPC: a binary RPC protocol from Google, defined with .proto files and running over HTTP/2 with Protobuf encoding. Great for fast, typed S2S inside a cluster.
  • GraphQL: a query language where the client picks the shape of the response from a single endpoint (usuallyPOST /graphql).
  • SOAP: an older XML-based RPC protocol with WSDL contracts. Still common in banking, government, and legacy enterprise.

Role by role

1. API server: the home position

This is what DaloyJS was designed for. You declare a route once, get validation, OpenAPI docs, a typed in-process client, and an autogenerated SDK out the other end.

ts
import { z } from "zod";
import { App } from "@daloyjs/core";
import { serve } from "@daloyjs/core/node";

const app = new App({ docs: true });

app.route({
  method: "GET",
  path: "/books/:id",
  operationId: "getBook",
  request: { params: z.object({ id: z.string() }) },
  responses: {
    200: { description: "Found", body: z.object({ id: z.string(), title: z.string() }) },
  },
  handler: async ({ params }) => ({ status: 200, body: { id: params.id, title: "..." } }),
});

serve(app, { port: 3000 });

See Getting started and Routing.

2. Web server (HTML and static files)

DaloyJS can return any Response, so you can serve HTML or files from it. But:

  • There's no file-system routing for pages.
  • There's no asset pipeline or hydration.
  • A CDN will serve static files faster and cheaper.

The only HTML DaloyJS ships out of the box is the Scalar / Swagger docs page at /docs. For real web content, put a CDN, a static host, or Next.js in front and let DaloyJS be the JSON layer.

3. Microservice (one of many)

DaloyJS is a strong fit here, with one small twist: when a service runs behind a mesh, sidecar, or private network, you don't need the browser-only protections like CSRF and same-origin enforcement. The framework ships a preset for exactly this case.

ts
import { App } from "@daloyjs/core";

const app = new App({
  preset: "internal-service", // turn off browser guards, keep input/parser/credential guards on
});

See Internal services & meshes and Modular monolith (you don't need a fleet of services to start).

4. Backend-for-Frontend (BFF): the sweet spot

BFF is arguably where DaloyJS is at its best. The combination you want is all first-party:

  • Typed upstream calls via Hey API codegen or the in-process typed client.
  • Safe egress via fetchGuard() , blocks SSRF, private CIDRs, and cloud-metadata IPs by default.
  • Session edge via session() (signed cookies, pluggable stores) and csrf() (double-submit or tokenless Fetch-Metadata).
  • Streaming to the browser via SSE and NDJSON helpers, plus compression() with BREACH-aware guards.
  • Edge runtimes: deploy on Cloudflare, Vercel Edge, Fastly Compute, or Lambda.

Pattern: your Next.js / React Native / iOS app talks only to the BFF; the BFF fans out to internal services and returns exactly what the UI needs.

5. API gateway, strong as "in-app gateway", not a replacement for Kong

DaloyJS gives you almost everything an API gateway does:

  • AuthN/Z: bearerAuth, basicAuth, jwt, jwk, requireScopes
  • Traffic: rateLimit (with Redis store), loadShedding, ipRestriction
  • Edge: secureHeaders, cors, csrf, compression, etag, requestId
  • Egress: fetchGuard (SSRF defaults)
  • Errors: RFC 9457 problem+json with prod redaction

What it does notdo (and shouldn't):

  • No dynamic upstream proxy. There is no proxyTo("http://upstream"); every route binds to in-process code.
  • No service discovery, circuit breakers, canary / weighted routing, or traffic mirroring.
  • No protocol translation (gRPC ↔ REST, SOAP ↔ REST).
  • No declarative gateway config (YAML, CRDs, admin API).

Use it as: the smart edge inside one service, or the front door for a small set of services you also own. Don't use it as: the only gateway sitting in front of a fleet of polyglot microservices. For that, run Kong / APISIX / Tyk / Envoy and put DaloyJS services behind it.

6. Load balancer: no

Load balancing is a TCP-level job. Use NGINX, HAProxy, AWS ALB/NLB, GCP Load Balancing, or Cloudflare. DaloyJS sits behindthe LB and serves requests; it doesn't distribute them. The framework does ship a behindProxy declarative model so it correctly reads X-Forwarded-* headers when the LB terminates TLS.

7. Server-side renderer (SSR): no

There is no JSX, React, Vue, or Svelte renderer in DaloyJS. No renderToString, no hydration, no file-system page router, no React Server Components. The framework deliberately stays in the REST/WS layer.

Recommended pattern: Next.js / Remix / Astro for SSR, DaloyJS for the API behind it. On Vercel you can even mount the same DaloyJS app as a Next.js route handler, see the Vercel adapter.

8. Webhook receiver: excellent

Webhooks are just HTTP POSTs with a signature header. DaloyJS has:

  • verifyWebhookSignature / signWebhookPayload , zero-knob HMAC helpers
  • timingSafeEqual for signature comparison
  • Schema validation on the body
  • Body-size limits and prototype-pollution-safe JSON enforced by the core
  • RFC 9457 error responses that webhook senders can parse

9. WebSocket server: excellent, with CSWSH guard

First-party WebSocket primitives run on the Node and Bun adapters with a Bun-style handler shape (open, message, close, drain, error).

Under secureDefaults, the framework refuses to register a WebSocket route unless you provide either a pre-upgrade authorization hook or explicitly opt out, and either an Origin allowlist or an explicit acknowledgement. That closes the Cross-Site WebSocket Hijacking (CSWSH) class of bug, cookie auth alone does not protect a WebSocket handshake.

See WebSocket primitives.

10. MCP server (HTTP transport): strong

The Model Context Protocol is JSON-RPC 2.0, transported over either stdio or HTTP + Server-Sent Events. DaloyJS handles the HTTP/SSE half natively:

  • Routes for POST / (JSON-RPC requests) and SSE streaming back
  • Schema validation on every request
  • Bearer auth + scopes for tool authorization
  • fetchGuard for any tool that makes outbound HTTP
  • Streaming helpers at @daloyjs/core/streaming

You bring the MCP framing (initialize, tools/list, tools/call) on top. DaloyJS won't generate it for you, there's no defineTool() primitive yet, but the HTTP, validation, auth, and SSE pieces are in-box.

11. gRPC server: no

gRPC needs HTTP/2 with Protobuf framing and trailers. DaloyJS is a REST framework around web-standard Request/Response. For gRPC, use @grpc/grpc-js or Connect (which can speak Connect-over-HTTP/1.1 and is friendlier in serverless). You can run a DaloyJS REST gateway in front of a gRPC backend if you want the external surface to be JSON.

12. GraphQL server: possible, not the framework's shape

DaloyJS is contract-first REST: one route, one schema, one OpenAPI operation. GraphQL is one route, one schema, many shapes. They're philosophically different.

If you must, you can mount GraphQL Yoga, Apollo, or Mercurius as a single POST /graphqlroute handler. You'll lose OpenAPI/typed-client benefits for that route. For new projects, either commit to REST (and use DaloyJS) or commit to GraphQL (and use a GraphQL framework).

13. SOAP server: no

SOAP is XML-over-HTTP with WSDL contracts. DaloyJS speaks JSON contracts via Standard Schema. There is no built-in XML parser, no WSDL generator, no SOAP envelope helper. If you have a legacy SOAP client that must talk to you, the practical pattern is: put a small adapter (Java, .NET, or a Node SOAP library like strong-soap) in front, and let it translate to a clean DaloyJS REST API behind.

Cheat sheet: pick the right tool

If your problem is…Reach for…Why not DaloyJS?
Distribute traffic across N copies of a serviceNGINX, HAProxy, ALB, CloudflareDaloyJS is the workload, not the router.
One front door for 30 polyglot servicesKong, APISIX, Envoy, TykNo dynamic upstream proxy or service discovery.
Render React/Vue pages on the serverNext.js, Remix, Astro, NuxtNo component renderer or hydration.
Binary, typed, fast S2S RPC inside a clustergRPC, ConnectREST/JSON only.
Single endpoint, client picks the response shapeGraphQL Yoga, ApolloDifferent paradigm; DaloyJS is one-route-per-operation.
Old enterprise integration over XML/WSDLA dedicated SOAP stack (or a translation adapter)No XML/WSDL primitives.
JSON API, validated, documented, secureDaloyJS-
Webhook receiver with HMACDaloyJS-
BFF that composes internal APIs for one UIDaloyJS-
Real-time chat / dashboards over WSDaloyJS-
MCP server over HTTP+SSEDaloyJS (you bring the MCP framing)-

A common deployment shape

Most real systems use several of these tools together. A typical production layout looks like this:

text
Browser / Mobile app


[ CDN ] ──> static assets, images


[ Load balancer ]              ← NGINX / ALB / Cloudflare


[ API gateway ]                ← Kong / APISIX / Envoy (optional, for many services)

        ├──> [ BFF - DaloyJS ]            ← session, CSRF, fetchGuard, typed upstream client
        │           │
        │           ├──> [ Catalog API - DaloyJS, internal-service preset ]
        │           ├──> [ Orders API  - DaloyJS, internal-service preset ]
        │           └──> [ Search API  - could be gRPC, GraphQL, anything ]

        ├──> [ Webhook receiver - DaloyJS ] ← Stripe, GitHub, Shopify

        ├──> [ WebSocket server - DaloyJS ] ← live updates

        └──> [ MCP server - DaloyJS ]       ← AI assistants call tools here

Every box marked DaloyJSis the same framework, the same contract style, the same security defaults, just configured for its role. The boxes that aren't DaloyJS exist because they're better at their specific job.

Where to go next