# Functions Editing Environment

Segment Functions create reusable code that can be run in your Segment workspace either as sources to format incoming events, or as destinations, to handle specific event types.

When you create a function, write code for it, and save it, the function appears in the Catalog in your workspace *only*. You can then deploy that function in your workspace just as you would a conventional source or destination.

> \[!NOTE]
>
> Access to Functions is controlled by specific [access management roles](#functions-permissions). You may need additional access to create and deploy functions.

## Creating functions

Only [Functions admins](#functions-permissions) can create or edit functions.

1. From your workspace, go to the **Catalog** and click the [Functions tab](https://app.segment.com/goto-my-workspace/functions/catalog).
2. Click **Create function**.
3. Select the type of function you want to build, and click **Build**.

   When you click **Build**, a code editor appears. Different template code is available depending on which type of function you created.
4. Use the editor to write the code for your function, configure settings, and test the function's behavior.
5. Once you finish writing your function, click **Configure** to give it a name.
6. Click **Create Function** to save your work and make this function available in your workspace.

After you click **Create Function**, the function appears on the [Functions catalog page](https://app.segment.com/goto-my-workspace/functions/catalog/) in your workspace.

## Editing a function

If you're a **Workspace Owner** or **Functions Admin**, you can manage your function from the [Functions catalog page](https://app.segment.com/goto-my-workspace/functions/catalog/).

If you're editing an existing function, you can **Save** changes without changing the behavior of existing instances of the function.

You can also choose to **Save & Deploy** to push changes to all, or specific functions in your workspace that are already deployed. You might need additional permissions to deploy these changes.

## Testing a function

You have the option to test your functions code with either a sample event or by loading a default event that you can customize yourself.

* **Sample event**: When you click **Test with custom event** you can select a sample event from any of your workspace sources to test this function.
* **Customize the event yourself**: When you click **customize the event yourself** a default event payload loads which you can modify with the desired data. You have the option to paste in a JSON event or click **Manual Mode** and type in the fields manually. If you'd like to locate a recent event from a source that's not available by following the sample event instruction:
  1. Navigate to the source debugger.
  2. Click the event you want to test and copy the raw JSON payload.
  3. Paste the raw JSON payload into your Function Editor.

Once the payload you want to test is ready, click **Run**.

> \[!NOTE]
>
> If you create settings in your function, then you need to fill in the setting values before clicking **Run**.

## Deploying source functions

> \[!NOTE]
>
> You must be a **Workspace Owner** or **Source Admin** to connect an instance of your function in your workspace.

1. From the [Functions tab](https://app.segment.com/goto-my-workspace/functions/catalog), locate the source function you want to deploy.
2. Click **Connect Source** and follow the prompts to configure the source. (You can access these settings later by navigating to the Source Settings page for your source function.)
3. Locate the webhook URL for the source, either on the **Overview** or **Settings → Endpoint** page.
4. Copy this URL and paste it into the upstream tool or service.

## Deploying destination functions

If you're editing an existing function, you can **Save** changes without changing the behavior of your deployed function. You can also choose to **Save & Deploy** to push changes to all, or specific functions in your workspace that are already deployed.

When you deploy your destination function in your workspace, you fill out the settings on the destination configuration page, similar to how you would configure a normal destination.

## Functions versioning

With Functions versioning, you can access a complete change history for each source or destination function. View version history and creation details, then use a unified or split display to compare code and restore previous versions of a function.

### View and compare version history

To view the version history of a function:

1. Navigate to **Connections > Catalog > Functions**.
2. Select your source or destination function.
3. Select **Edit Function**, then click **Version history**.

Select previous versions to compare code using a *unified* or *split* view. With the split view, Segment displays the latest version on the left and the version you've selected on the right.

> \[!TIP]
>
> Unified and split compare screens are read-only. While you can copy code, you can't make changes directly from these screens.

#### `LATEST` and `DEPLOYED` versions

In the Version History panel, Segment displays `LATEST` and `DEPLOYED` labels that represent a function version state. You'll see the `LATEST` version at the top.

Segment labels a version as the `LATEST` when:

* You save a change to the function source code, but don't deploy the function at the same time.
* You [restore a previous version](#restore-a-previous-version) from your function's version history.

The `DEPLOYED` version is the function version that's currently deployed.

### Restore a previous version

To restore a previous function version:

1. Select the function you want to restore.
2. Click **Restore this version**.
   * Segment creates a duplicate of the selected version and labels it as the `LATEST` version.
3. Click **Restore** on the confirmation screen.
4. To deploy the restored version, click **Save and Deploy** on the Source Code screen.

### Use Versioning with Segment's Public API

You can use Functions Versioning with Segment's [Public API](https://docs.segmentapis.com/tag/Functions) to retrieve version history records and source code, as well as to restore previous versions.

Here are some Public API use case examples:

**Get Version history**: Use the `/versions` endpoint to retrieve a list of version records and metadata of a certain page size. You can also use this endpoint to get version source code for a given version ID.

**Restore a previous version**: Use the `/restore` endpoint to restore a previous function version. This creates a new version with the same source as the version you are restoring.

**Create or update versions**: Create or update a function to add a version record and save the source code.

**Deploy a function**: Use the Public API to deploy a function. After you deploy, Segment marks the function version as `DEPLOYED`. Learn more about function version states in the [Latest and deployed versions](#latest-and-deployed-versions) section.

View Segment's [Public API](https://docs.segmentapis.com/tag/Functions) docs for more information on how to use Functions Versioning with the Public API.

## Functions permissions

Functions have specific roles which can be used for [access management](/docs/segment/segment-app/iam/) in your Segment workspace.

Access to functions is controlled by two permissions [roles](/docs/segment/segment-app/iam/roles/):

* **Functions Admin:** Create, edit, and delete all functions, or a subset of specified functions.
* **Functions Read-only:** View all functions, or a subset of specified functions.

You also need additional **Source Admin** permissions to enable source functions, connect destination functions to a source, or to deploy changes to existing functions.

## ️Settings and secrets

Settings allow you to pass configurable variables to your function, which is the best way to pass sensitive information such as security tokens. For example, you might use `settings` as placeholders to use information such as an API endpoint and API key. This way, you can use the same code with different settings for different purposes. When you deploy a function in your workspace, you are prompted to fill out these settings to configure the function.

To use settings:

1. Add a setting in the **Settings** tab in the code editor:

![A screenshot of the functions settings tab.](https://docs-resources.prod.twilio.com/1c4c64e35da90a4a5b58ca20bc35bc617499ffc8a2964ae58ef713ae6b342d02.png)

2. Click **Add Setting** to add your new setting.
3. Configure the details about this setting, which change how it's displayed to anyone using your function:

* **Label** - Name of the setting, which users see when configuring the function.
* **Name** - Auto-generated name of the setting to use in function's source code.
* **Type** - Type of the setting's value.
* **Description** - Optional description, which appears below the setting name.
* **Required** - Enable this to ensure that the setting cannot be saved without a value.
* **Secret** - Enable this to ensure that sensitive data, like API key values or passwords, are not displayed in the Segment UI.

As you change the values, a preview to the right updates to show how your setting will look and work.

4. Click **Add Setting** to save the new setting.

Once you save a setting, it appears in the **Settings** tab for the function. You can edit or delete settings from this tab.

## Runtime and dependencies

Segment Functions run on the Node.js LTS runtime (currently v20). This keeps the runtime current with industry standards and security updates.

Based on the [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) and [Node.js](https://nodejs.org/en/about/previous-releases) support schedule, production applications should only use Node.js releases that are in Active LTS or Maintenance LTS.

When Segment upgrades the Functions runtime to a new LTS version, existing functions automatically use the new runtime after their next deployment. Segment recommends checking your function after deployment to ensure everything works as expected, since dependency or syntax changes between Node.js versions might affect your function's behavior.

Functions don't support importing dependencies, but you can [contact Segment Support](https://segment.com/help/contact/) to request that one be added.

The following dependencies are installed in the function environment by default:

* [`atob v2.1.2`](https://www.npmjs.com/package/atob) exposed as `atob`
* [`aws-sdk v2.488.0`](https://www.npmjs.com/package/aws-sdk) exposed as `AWS`
* [`btoa v1.2.1`](https://www.npmjs.com/package/btoa) exposed as `btoa`
* [`fetch-retry`](https://www.npmjs.com/package/fetch-retry) exposed as `fetchretrylib.fetchretry`
* [`form-data v2.4.0`](https://www.npmjs.com/package/form-data) exposed as `FormData`
* [`@google-cloud/automl v2.2.0`](https://www.npmjs.com/package/@google-cloud/automl) exposed as `google.cloud.automl`
* [`@google-cloud/bigquery v5.3.0`](https://www.npmjs.com/package/@google-cloud/bigquery) exposed as `google.cloud.bigquery`
* [`@google-cloud/datastore v6.2.0`](https://www.npmjs.com/package/@google-cloud/datastore) exposed as `google.cloud.datastore`
* [`@google-cloud/firestore v4.4.0`](https://www.npmjs.com/package/@google-cloud/firestore) exposed as `google.cloud.firestore`
* [`@google-cloud/functions v1.1.0`](https://www.npmjs.com/package/@google-cloud/functions) exposed as `google.cloud.functions`
* [`@google-cloud/pubsub v2.6.0`](https://www.npmjs.com/package/@google-cloud/pubsub) exposed as `google.cloud.pubsub`
* [`@google-cloud/storage v5.3.0`](https://www.npmjs.com/package/@google-cloud/storage) exposed as `google.cloud.storage`
* [`@google-cloud/tasks v2.6.0`](https://www.npmjs.com/package/@google-cloud/tasks) exposed as `google.cloud.tasks`
* [`hubspot-api-nodejs`](https://www.npmjs.com/package/@hubspot/api-client) exposed as `hubspotlib.hubspot`
* [`jsforce v1.11.0`](https://www.npmjs.com/package/jsforce) exposed as `jsforce`
* [`jsonwebtoken v8.5.1`](https://www.npmjs.com/package/jsonwebtoken) exposed as `jsonwebtoken`
* [`libphonenumber-js`](https://www.npmjs.com/package/libphonenumber-js) exposed as `libphonenumberjslib.libphonenumberjs`
* [`lodash v4.17.19`](https://www.npmjs.com/package/lodash) exposed as `_`
* [`mailchimp marketing`](https://www.npmjs.com/package/@mailchimp/mailchimp_marketing) exposed as `mailchimplib.mailchimp`
* [`mailjet`](https://www.npmjs.com/package/node-mailjet) exposed as `const mailJet = nodemailjet.nodemailjet;`
* [`moment-timezone v0.5.31`](https://www.npmjs.com/package/moment-timezone/v/0.5.31) exposed as `moment`
* [`node-fetch v2.6.0`](https://www.npmjs.com/package/node-fetch) exposed as `fetch`
* [`oauth v0.9.15`](https://www.npmjs.com/package/oauth) exposed as `OAuth`
* [`@sendgrid/client v7.4.7`](https://www.npmjs.com/package/@sendgrid/client) exposed as `sendgrid.client`
* [`@sendgrid/mail v7.4.7`](https://www.npmjs.com/package/@sendgrid/mail) exposed as `sendgrid.mail`
* [`skyflow`](https://www.npmjs.com/package/skyflow-node) exposed as `skyflowlib.skyflow`
* [`stripe v8.115.0`](https://www.npmjs.com/package/stripe) exposed as `stripe`
* [`twilio v3.68.0`](https://www.npmjs.com/package/twilio) exposed as `twilio`
* [`uuidv5 v1.0.0`](https://www.npmjs.com/package/uuidv5) exposed as `uuidv5.uuidv5`
* [`winston v2.4.6`](https://www.npmjs.com/package/winston) exposed as `const winston = winstonlib.winston`
* [`xml v1.0.1`](https://www.npmjs.com/package/xml) exposed as `xml`
* [`xml2js v0.4.23`](https://www.npmjs.com/package/xml2js) exposed as `xml2js`
* [`zlib v1.0.5`](https://www.npmjs.com/package/zlib) exposed as `zlib.zlib`

  <br />

  ```js
  async function onRequest(request, settings) {
       uuidv5 = uuidv5.uuidv5;
       console.log(typeof uuidv5);

        //Generate a UUID in the default URL namespace
        var urlUUID = uuidv5('url', 'http://google/com/page');
        console.log(urlUUID);

        //Default DNS namespace
        var dnsUUID = uuidv5('dns', 'google.com');
        console.log(dnsUUID);
    }
  ```

  `zlib`'s asynchronous methods `inflate` and `deflate` must be used with `async` or `await`. For example:

  ```js
  zlib = zlib.zlib;  // Required to access zlib objects and associated functions
  async function onRequest(request, settings) {
  const body = request.json();

  const input = 'something';

  // Calling inflateSync method
  var deflated = zlib.deflateSync(input);

  console.log(deflated.toString('base64'));

  // Calling inflateSync method
  var inflated = zlib.inflateSync(new Buffer.from(deflated)).toString();

  console.log(inflated);

  console.log('Done');
  }
  ```

The following Node.js modules are available:

* [`crypto` Node.js module](https://nodejs.org/dist/latest-v10.x/docs/api/crypto.html) exposed as `crypto`.
* [`https` Node.js module](https://nodejs.org/api/https.html) exposed as `https`.

[Other built-in Node.js modules](https://nodejs.org/api/modules.html) aren't available.

For more information on using the `aws-sdk` module, see how to [set up functions for calling AWS APIs](/docs/segment/connections/functions/aws-apis/).

### Caching

Basic cache storage is available through the `cache` object, which has the following methods defined:

* `cache.load(key: string, ttl: number, fn: async () => any): Promise<any>`
  * Obtains a cached value for the provided `key`, invoking the callback if the value is missing or has expired. The `ttl` is the maximum duration in milliseconds the value can be cached. If omitted or set to `-1`, the value will have no expiry.
* `cache.delete(key: string): void`
  * Immediately remove the value associated with the `key`.

Some important notes about the cache:

* When testing functions in the code editor, the cache will be empty because each test temporarily deploys a new instance of the function.
* Values in the cache are not shared between concurrently-running function instances; they are process-local which means that high-volume functions will have many separate caches.
* Values may be expunged at any time, even before the configured TTL is reached. This can happen due to memory pressure or normal scaling activity. Minimizing the size of cached values can improve your hit/miss ratio.
* Functions that receive a low volume of traffic may be temporarily suspended, during which their caches will be emptied. In general, caches are best used for high-volume functions and with long TTLs.
  The following example gets a JSON value through the cache, only invoking the callback as needed:

```js
const ttl = 5 * 60 * 1000 // 5 minutes
const val = await cache.load("mycachekey", ttl, async () => {
    const res = await fetch("http://echo.jsontest.com/key/value/one/two")
    const data = await res.json()
    return data
})
```
