---
title: Bun apps
description: Rules for Bun apps without a framework, currently apps/api-ingest, apps/worker-errors and apps/worker-jobs.
---

Bun processes without a framework. What each one does is in [Self-hosting → Services](/self-hosting/services/api-ingest).

- Logic lives in `packages/`. A route or job handler only decodes its input and calls a function from there; nothing here redefines shared vocabulary or models.
- Filenames are kebab-case: `otlp-route.ts`, `register-alert-workers.ts`. Route handlers are exempt from verb-first names. Prefer Bun APIs.
- Health comes from `@openperf/server/health`: `createHealthz` for readiness, `serveHealth` next to `/health/live`, and `handleShutdown` for SIGTERM and SIGINT.

## api-ingest

Routes live in `src/routes/`, assembled by `server.ts`. They answer OTLP conventions: empty protobuf or JSON bodies on success, and status codes mapped from domain errors.

## worker-errors

Queue handlers live in `src/jobs/`. Its pg-boss instance neither supervises queues nor runs schedules.

## worker-jobs

The only pg-boss instance that supervises queues and runs schedules. Handlers live in `src/jobs/register-<domain>-workers.ts`. A new job gets its function in `packages/server/src/jobs`, its queue in `jobQueues` and its payload type in `JobPayloads`.
