Life Cycle

Elysia supports Life Cycle events, which trigger at specific moments.

A Middleware or Hook acts as an event listener, allowing you to "hook" into these events. This Hook capability enables you to modify data as it moves through the data pipeline.

Whether you aim to implement a custom body parser, generate a tailored response based on your handler, or set up an authentication guard, the Hook empowers you to harness the full potential of Elysia.

Elysia Life Cycle

Life Cycle

The life cycle events in Elysia consists of:

  • Start: setup some requirement before the server start serving (Start Loop)
  • Request: get notified of every new request
  • Parse: array of functions to parse the body
  • Routing: picking which handler to use based on path and method
  • Transform: transform request and context before validation
  • Validation: validate the requirement of an incoming request
  • Before Handle: custom requirement to check before the main handler, can skip the main handler if response returned.
  • Main Handler: function assigned to the path
  • Validation (Response only): validate the response
  • After Handle: map returned value into a proper response
  • Error: handle error thrown during processing request
  • Response: send a Response back to the client (Stop Loop)
  • Stop: call after the server stop serving, setup a cleanup function for graceful shutdown

Although the hook is designed to be assignable to many events, not all event is listenable:

The listenable event consists of:

  • Start
  • Request
  • Parse
  • Transform
  • Before Handle
  • After Handle
  • Error
  • Response
  • Stop


The hook is separated into 2 types:

  • Global Hook: Listen to event globally
  • Local Hook: Only listener to a specific route

Global hook

The global hook can listen to all events in the listenable list, which will be applied to all handlers in scope.

To listen to an event, use .on[EventName](callback)

// .on[EventName](callback)

// .on(eventName, callback)
app.on("request", callback);

Local Hook

The local hook can only access event AFTER routing as it's assigned to a specific path handler only.

Which consists of:

  • Transform
  • Schema (Not in Event Listener): define validation for the specific path
  • Before Handle
  • After Handle

To use a local hook, pass it as the third argument in the handler

app.get("/", () => "Hello", {
  beforeHandle: ({ set, request: { headers } }) => {
    if (!isSignIn(headers)) {
      set.status = 401;
      return "Unauthorized";

A local hook can accept an array of functions.

The best practice is to break down a function into a smaller reusable function.

app.get("/", () => "Hello", {
  beforeHandle: [isUserExisted, isSignIn],
  afterHandle: [addAdditionalHeader],