App
Create one application at boot. Configure its services, use request-local state and close the resources you own.
On this page
Source-backed MarkdownCreate one App per process
App is the framework service hub, not an HTTP server. Your HTTP server, command or worker creates it once at boot. The first-app guide shows a complete Fastify entry point with no database requirement.
Use a service
Import App and app from @db3.ai/app/server. Constructing new App(options) makes it active. app().storage, app().auth, app().queue and the other getters create services lazily and reuse them.
Do not create another App per request. The active App is process-global; creating a second replaces the active reference. Calling app() before boot throws an explicit error.
Configure the runtime
Pass general values through config. Use storage, auth, queue, log, url and serializer options for the corresponding service. Cache, Media and Security also read their named configuration sections.
Database-backed services resolve the active App database. Normal feature functions should not accept optional Knex arguments. Use ActiveRecord.withDb() for a scoped transaction; migrations remain an application deployment step.
Set dbOptions.syncColumns to false for a migration-owned application schema. The default development-oriented safe column synchronization is not a substitute for reviewed production migrations.
Keep request state isolated
Wrap the complete request work in application.requestContext.run(). Use set(), get() and remember() inside that boundary. remember() shares a value or in-flight promise within one request and removes rejected promises so a later attempt can retry.
Auth relies on this context for current user and token state. Do not keep authenticated users on process-global application properties. A route handler wrapper covers its callback, not earlier middleware that ran outside it.
Run and shut down
The host owns listening, signals and worker processes. Close the HTTP listener or stop accepting work before App.close(). The first-app entry point handles SIGINT and SIGTERM.
App.close() clears the active reference, detaches the scheduler recorder, clears event listeners, closes Cache and Logging, and destroys a framework-owned database connection. An injected database remains caller-owned.
It does not drain queue workers or close a Redis queue driver. Stop workers and close their owned transports before closing the App, while jobs can still resolve app(). Custom application services must also close any resources they introduce.
Testing
Construct the real application factory and use HTTP injection for route tests. Close it in finally. Use a generated disposable database when testing database-backed features; do not mock ActiveRecord or point tests at an application database.
Coverage and reference
The first-app test exercises configuration, request handling, validation and shutdown. Service-owned Server tests additionally cover request isolation and active-context lifecycle. Custom service shutdown and production deployment need their own application tests.
The Source-backed Markdown version includes the detailed service reference and extension example. The installed AppOptions and RequestContext declarations define the complete typed options; they are not a claim that every option has a walkthrough.