Separate Backend
Run @repo/api as a standalone Hono server on API_PORT with its own scaling, trusted 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
| Reason | Why separate helps |
|---|---|
| Independent scaling | Scale the API and frontend on different curves |
| Multiple frontends | One API serves many origins - web, mobile, partner apps |
| Operational isolation | A frontend deploy or crash cannot take the API down |
If none apply, fullstack is simpler: fewer hosts, no CORS, no API_URL.
The standalone entry point
const apiServer = serve({ fetch: app.fetch, port: env.API_PORT });
// SIGINT / SIGTERM -> closeRedis(), then apiServer.close()- Listens on
API_PORT(default3010). - Closes the Redis connection, then drains the server on
SIGINT/SIGTERM. - A fatal bootstrap error exits with code
1.
separate deploys only to a long-running host - Docker on Render, Fly.io, Railway, Coolify, Dokploy, or a VPS. The CLI blocks separate + vercel: a graceful-shutdown process cannot run as serverless functions.
Wiring frontend to backend
Both sides need configuring before any browser call succeeds.
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, and every browser call is rejected in production.https://api.yourdomain.com) via NEXT_PUBLIC_API_URL.| Var | Side | Purpose |
|---|---|---|
API_PORT | Backend | Port the standalone server binds (default 3010) |
TRUSTED_ORIGINS | Backend | Comma-separated allowed origins → config.origins |
API_URL | Backend | Validated runtime base URL; falls back to the frontend's public API URL var |
NEXT_PUBLIC_API_URL | Frontend | Public API URL the client targets - set to the backend base URL |
Switching architecture later needs no CLI re-run: the API code is identical, only the host and env vars differ. Follow Switch to separate or Switch to fullstack - both rewire in place and preserve your customized packages/config and .env, which re-running the CLI would regenerate wholesale.
Coolify
Deploy the node target to Coolify, a self-hosted PaaS that builds the standard Docker image on your own VPS and fronts it with its built-in proxy.
Switch to Separate
Move a fullstack project to a standalone backend in place - unmount the API route, repoint the client, and move DB ownership, with no CLI re-run.