GenerateSaaS

Separate Backend

Run the Hono API as a standalone server with its own scaling, origins, and host.

In separate architecture, apps/backend/src/index.ts serves @repo/api via @hono/node-server on API_PORT as its own process. Choose it over fullstack when the API needs to scale, deploy, or fail independently of any frontend.

When to choose separate

ReasonWhy separate helps
Independent scalingScale the API and frontend on different curves.
Multiple frontendsOne API serves many origins (web, mobile, partner apps).
Operational isolationA frontend deploy or crash can't take the API down.

If none of these apply, fullstack (the frontend hosts @repo/api in-process) is simpler - fewer hosts, no CORS, no API_URL.

The standalone entry point

apps/backend/src/index.ts boots one Hono server with graceful shutdown:

const apiServer = serve({ fetch: app.fetch, port: env.API_PORT });
// SIGINT / SIGTERM -> closeRedis(), then apiServer.close()
  • Listens on API_PORT (default 3010).
  • Closes the Redis connection, then drains the server on SIGINT/SIGTERM.
  • A fatal bootstrap error exits with code 1.

Long-running host only

separate deploys only to a long-running host (Docker on Render, Fly.io, Railway, Coolify, Dokploy, or a VPS). The CLI blocks separate + vercel with INCOMPATIBLE_ARCH_TARGETS - a graceful-shutdown process can't run as serverless functions.

Wiring frontend to backend

Cross-origin requests need both sides configured before any browser call succeeds.

Backend - set TRUSTED_ORIGINS (comma-separated, no trailing slash) to every frontend origin. It becomes config.origins, which CORS and auth enforce. Unset, it falls back to localhost:3000, :3001, :5173.
Frontend - point the API client at the backend base URL via the public API URL var (e.g. https://api.yourdomain.com). The exact key carries a framework prefix - see your framework's env reference.
Front both apps with a proxy by host/path. See Reverse proxy.
VarSidePurpose
API_PORTBackendPort the standalone server binds (default 3010).
TRUSTED_ORIGINSBackendComma-separated allowed origins → config.origins.
API_URLBackendValidated runtime base URL; falls back from the frontend's public API URL var.
*_PUBLIC_API_URLFrontendFramework-prefixed public API URL the client targets - set to the backend base URL.

Frequently asked questions

Do I need a reverse proxy? Yes for production - route the root domain to the frontend and api.yourdomain.com (or yourdomain.com/api/) to the backend. See Reverse proxy.

What happens if TRUSTED_ORIGINS is wrong? CORS and auth reject every browser call. List each real frontend origin exactly, with no trailing slash.

Can I switch architecture later? Yes - the API code is identical; only the host and env vars differ. Follow Switch to separate (or back to fullstack) - an in-place rewiring that preserves your customized packages/config and .env. Don't re-run the CLI; it regenerates both wholesale.

On this page