Skip to content

Provide a mechanism to share data between appStart, preInvocation, invocation, and appTerminate in Node.js Azure Functions #373

@kamaz

Description

@kamaz

Description

Currently, there is no clear or documented way to persist or share contextual data between application startup, pre-invocation, and invocation stages within Azure Functions for Node.js.

Based on earlier discussions and PRs, there appears to have been prior work to expose this capability, but it's not currently available or documented.

Background and References

There was a proposal to expose this via the context object as part of this PR:

🔗 Azure Functions Node.js Library — PR #111

Previously, there was an appHookData property defined in the types here:

🔗 types-core/index.d.ts (line 86)

And the Node.js worker implementation still references this field internally:

🔗 Azure Functions Node.js Worker — PR #621 (line 49)

However, the documentation and current API surface don’t clarify how developers can leverage or replicate this functionality and appDataHook returns null when referenced.

Problem Statement

When implementing complex or long-lived integrations (e.g., with Service Bus, Key Vault, or database clients), developers need a way to:

  • Initialise shared resources during appStart (e.g., open connections, load clients, or prefetch configuration).
  • Access these shared objects during function invocation or pre-invocation for telemetry, metrics, or request handling.
  • Clean up resources during appTerminate.

Currently, there’s no reliable way to pass such state or objects between these lifecycle hooks.

Example Use Case

The following pseudocode illustrates the desired behaviour:

app.hook.appStart(async (context) => {
  // Initialize shared client once at startup
  context.hookData.client = new ServiceBusClient();
});

app.hook.preInvocation(async (context) => {
  // Use client before invocation (e.g., emit metrics)
  context.hookData.client.recordMetric('invocation-start');
});

app.http('handler', {
  handler: async (request, context) => {
    // Access same client during invocation
    await context.hookData.client.sendMessage(request.body);
  },
});

app.hook.postInvocation(async (context) => {
  context.hookData.client.recordMetric('invocation-end');
});

app.hook.appTerminate(async (context) => {
  // Gracefully close client connection
  await context.hookData.client.close();
});

This would enable developers to manage lifecycle-bound resources consistently without creating global variables or redundant connections.

Suggested Solution / Questions

  • Can we expose a standard context.hookData or equivalent mechanism that persists across the function lifecycle?
  • Alternatively, can this functionality be safely implemented using appHookData if it’s re-enabled?
  • If the feature is deprecated, can guidance be provided for how to maintain application-wide state between hooks?

Example Scenario

Using this approach would allow developers to:

  • Initialise a Service Bus client at app start.
  • Reuse it during each invocation.
  • Ensure it’s properly closed on app termination.

Without this, developers must rely on global variables or re-initialize clients per invocation, which impacts performance and reliability.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions