nitrojs / nitrojs/nitro

Bootstrapping / startup logic

Open
#3,872 5 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

v2 v3
Dominant language
TypeScript
Stars
11.2k
Forks
899
Avg merge
2d 24m
Merged PRs (30d)
40

Description

Hello! Thank you for this great project.

However, I'm looking for guidance on the recommended way to implement startup behavior in a Nitro application, such as performing asynchronous initialization tasks (e.g., connecting to a database, running migrations, warming caches, or initializing external services) before the server begins accepting requests.

Currently, the natural approach seems to be using Nitro plugins (defineNitroPlugin), as they run during server initialization. However, their behavior leads to several problematic issues:

  1. Errors in plugin code do not cause the server process to exit
    If an error is thrown synchronously or rejected in an async plugin (even with await), the server continues to start and listen for requests. This is counter-intuitive and dangerous in production, as it can result in a running server that is in a partially initialized or broken state (e.g., missing database connection), leading to runtime errors on the first request.

  2. No waiting for async plugin completion
    Even if a plugin is async (e.g., defineNitroPlugin(async nitro => { await someLongInit(); })), the server does not await its completion. This creates a race condition: the server starts listening and can accept requests before the initialization is finished.

These behaviors make it risky to perform critical startup logic in plugins.

Expected Behavior
  • Critical initialization errors should fail fast by exiting the process (similar to how uncaught exceptions behave in Node.js).
  • The server should only start listening after all plugins (or at least async startup tasks) have successfully completed.
Possible Solutions / Feature Request

If plugins are intended for this use case:

  • Make plugin execution fully awaited before the server listens.
  • Propagate unhandled errors/rejections from plugins to exit the process (with a non-zero code in production).

Alternatively, provide a dedicated runtime hook for startup initialization, such as:

  • nitro.hooks.hook('bootstrap', async () => { ... }) hook that is awaited after plugin registration but before listening.

Thanks!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing Nitro plugin initialization and the server listen lifecycle, then reproduce the behavior with an async defineNitroPlugin that delays or rejects. Done means startup waits for critical initialization before accepting requests and initialization failures prevent normal server startup; the issue does not name specific files or tests to run.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.