---
source_url: https://www.pubnub.com/docs/message-processing/serverless/development
title: Functions development
updated_at: 2026-09-30T07:20:08.000Z
---

# Functions development

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

A PubNub Function is a JavaScript module with one default export: a handler function that PubNub calls when the configured trigger fires. This page explains how that handler is structured, what objects it receives, how Promises work in Functions, how to chain Functions, and what the Package/Revision/Deployment model means before your code goes live.

For trigger types and execution modes, see [Function types](https://www.pubnub.com/docs/serverless-sdk/function-types.md). For per-execution limits, see [API limits](https://www.pubnub.com/docs/serverless-sdk/api-limits.md).

## Handler signatures

The handler signature varies by event type:

* **Most event types** receive a `request` object:

   ```javascript
   export default async (request) => {
       // Your business logic here. Await every async call.
       return request.ok();
       // return request.abort(); to fail execution
   };
   ```

* **On Request** receives both `request` and `response`:

   ```javascript
   export default async (request, response) => {
       // Your code here. Await every async call.
       return response.send();
   };
   ```

* **On Interval** receives an `event` object instead of `request`:

   ```javascript
   export default async (event) => {
       // Your code here. Await every async call.
       return event.ok();
   };
   ```

The handler must return a Promise, which an `async` handler always does. Execution is complete when that Promise settles. Only work you await before the handler returns is guaranteed to finish, and only errors from that work reach your handler. Don't rely on anything you start without awaiting it: whether it completes isn't guaranteed and can differ between Functions runtime versions. Synchronous triggers (Before Publish, Before Signal, On Request) hold the publisher or HTTP caller waiting until the Promise settles.

## Handler objects

Most trigger types pass a `request` object. On Request passes both `request` and `response`. On Interval and Subscribe on Interval pass an `event` object.

Use `request.message` to read or change a message in a synchronous trigger. Call `request.abort()` to prevent delivery. On Request uses `response.send()` to return an HTTP response.

For every field, method, and trigger-specific object contract, see [Request and response objects](https://www.pubnub.com/docs/serverless-sdk/request-response-objects.md).

## Promises

Functions use ES6 Promises for all async operations and support `async`/`await`. The `promise` object is available in every Function without a `require()` call.

`Promise.all()` runs multiple async calls in parallel and waits for all of them before proceeding. This example fetches a username from the KV store and an IP address from a web service at the same time, then updates the message with both results:

```javascript
export default async (request) => {
    const store = require('kvstore');
    const xhr = require('xhr');

    try {
        const [fullName, ipResponse] = await Promise.all([
            store.get('fullName'),
            xhr.fetch('https://httpbin.org/ip'),
        ]);

        request.message.fullNameResult = fullName;
        request.message.ip = JSON.parse(ipResponse.body).origin;

        return request.ok();
    } catch (err) {
        console.log(err);
        return request.abort(err);
    }
};
```

Await every async call before the handler returns. If you return while a call is still pending, your Function doesn't see whether that call succeeded and can't handle its error.

## Chain Functions

A Function can trigger other Functions by publishing to a channel that another Function runs on. Your Function waits only until PubNub accepts the publish. The downstream Function then runs on its own, and your Function doesn't wait for it to finish.

Await the publish before you return, and handle its error:

```javascript
export default async (request) => {
    const pubnub = require('pubnub');

    request.message.hello = 'world!'; // augment hello = world

    try {
        const publishResponse = await pubnub.publish({
            channel: 'hello_universe',
            message: request.message,
        });
        console.log('Published to hello_universe with timetoken', publishResponse[2]);
    } catch (err) {
        console.error('Publish to hello_universe failed:', err);
    }

    return request.ok();
};
```

This example still delivers the original message when the downstream publish fails. Return `request.abort()` from the `catch` block instead if the original message must not be delivered without it.

Don't skip the `await` to return sooner. A publish you don't await isn't guaranteed to complete, and nobody sees it fail. If a side effect shouldn't delay a synchronous trigger such as Before Publish, move it to an After Publish Function on the same channel instead.

Functions support chaining up to 3 hops, so a Function can trigger at most two more Functions downstream. Trigger each hop in the sequence using `pubnub.publish()` or `pubnub.signal()`. The system detects and blocks infinite loops, but design your logic to avoid circular chains rather than relying on that detection.

Group Functions you intend to chain in the same Package. Starting or stopping a Package affects all its Functions at once, so chained Functions that share a Package are easier to manage.

## Package, Revision, and Deployment lifecycle

Before a Function processes live traffic, it must be organized into a Package and activated through a Deployment:

* **Package.** A Package groups related Functions. It is the unit you start and stop together. All Functions in a Package share a lifecycle: starting the Package starts all of them, stopping it stops all of them.
* **Revision.** A Revision is a saved version of a Package. PubNub creates the first Revision automatically when you create the Package. Saving a code or event-type change creates a new Revision. Revisions are immutable once saved, so you can re-deploy an earlier one to roll back.
* **Deployment.** A Deployment links a Revision to one or more keysets. Only a deployed Revision processes live traffic. You can keep one Revision running in production while testing a newer one in a separate deployment. Stopping a Deployment stops all Functions in the Package on those keysets. Messages still flow through PubNub, but On Request endpoints return `404 Not Found` until a Revision is started again.

## Code environment

Functions run in a sandboxed JavaScript runtime. The runtime does not support:

* Native Node.js modules (such as `fs` or `http`)
* npm packages
* The `process` global
* WebSocket connections

Use the built-in modules for all external calls and storage. They load with `require()` and are not subject to the npm restriction. See [Built-in modules](https://www.pubnub.com/docs/message-processing/serverless/overview.md#built-in-modules) for the full list.

Last updated at: 2026-09-30T07:20:08.000Z
