OpinionDefaults

Why DaloyJS Feels Like the Backend Default We Should Have Had Already

DaloyJS feels underrated because it starts with the unglamorous parts that modern backend teams actually need: install-time safety, runtime guardrails, and one route definition that keeps types, docs, and clients aligned.

Devlin DuldulaoFullstack cloud engineer6 min read

I have shipped enough backends to know that most teams do not lose sleep because routing is hard. They lose sleep because security gets treated like a side quest. Someone wires up an API, adds a database, maybe a queue if they are feeling brave, and ships it with the confidence of a person assembling furniture from one blurry photo. Sometimes that works. Then Monday happens.

DaloyJS feels like the backend default we should have had already because it starts with the right assumptions: developers are busy, AI agents are now part of the toolchain, and attackers are not waiting politely for everybody to finish the tutorial.

The boring controls are the good controls

The supply-chain part matters more than people like to admit. Attackers are using LLMs to scale package impersonation, dependency reconnaissance, and workflow abuse. The answer is not to panic and become a security monk. The answer is to ship a sane set of defaults.

ini
ignore-scripts=true
minimum-release-age=1440
verify-store-integrity=true
strict-peer-dependencies=true

Those lines are not glamorous. They are also the sort of thing that quietly prevents extremely annoying incidents. I trust boring controls more than dramatic postmortems.

Runtime guardrails should be part of the framework story

I also like that DaloyJS treats security as product behavior instead of a lecture. The framework is explicit about CSRF, IP restriction, SSRF guardrails, open redirect handling, login throttling, and other defensive layers that too many teams only discover after reading a report with the phrase "proof of concept" in it.

More importantly, it keeps the core development flow readable. One route definition becomes validation, types, OpenAPI 3.1, docs, and typed clients. That means fewer places for truth to drift and fewer moments where the code says one thing while the generated docs say something charmingly fictional.

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

const app = new App({
  bodyLimitBytes: 1 << 20,
  requestTimeoutMs: 5_000,
});

app.use(requestId());
app.use(secureHeaders());
app.use(rateLimit({ windowMs: 60_000, max: 120 }));

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

serve(app, { port: 3000 });

Why this feels underrated

DaloyJS is solving the unglamorous problems first: install-time safety, runtime guardrails, contract-first design, and deploy-time discipline. That is not flashy. It is just useful. I would rather have a framework that removes common failure modes than one that gives me a tenth way to name a router group.

If I were starting a new REST API today, I would want the framework to assume people are busy and production is real. DaloyJS is one of the few that feels built around that premise. Less drama, fewer surprises, and ideally fewer meetings about how a suspicious package ended up in the lockfile.

For the more detailed versions of this argument, read Secure by Defaultand the scaffolding post. They make the practical case better than any slogan can.

About the author: Has shipped enough backends to know that the scary part is usually not routing. It is everything around routing.