---
schema_version: "1"
id: 5e3a3c3dee5386c0a82d181ecd852558cda472fe7cb5d80c01ef3af3c521ccae
title: Develop Functions
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/salesforce-functions/functions/guide/dev-guide/develop.md
canonical_url: https://developer.salesforce.com/docs/platform/functions/guide/develop.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: bfb49283cecbb13e0f5d6403b736d743912bece8908e9cdbcbe5dd05621e7337
products:
  - Salesforce Functions
---
# Develop Functions

This section explains the basic developer workflow when developing a new function. This section also details how to add build and run-time configurations for your functions.

When you're done developing your function, [deploy your function](https://developer.salesforce.com/docs/platform/functions/guide/deploy.md) to a Salesforce compute environment and [invoke your function](https://developer.salesforce.com/docs/platform/functions/guide/invoke-apex.md) from your org.

## Create a Function Project

To create a function, start by [creating a Salesforce DX project](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_create_new.htm).

The DX project name you choose represents the Salesforce Functions project name, which you use when invoking a deployed function. A Salesforce Functions project name must be unique to the org. The project name is listed in the sfdx-project.json configuration file.

Next, use the `generate:function` command to populate your project with the template source files and the metadata file for your function. For example, to create a JavaScript-based function named `myfunction`, use the following command from your DX project root directory:

```bash
sf generate function -n myfunction -l javascript
```

The function name must be only lowercase letters or numbers, and must start with a lowercase letter.

**note:** The only supported languages for the `-l`/`--language` arguments are `javascript`, `typescript`, and `java`.

Creating a function adds the `<project root>/functions/<function name>` directory to your DX project and creates default source files and build definition files for the function in that directory. Here’s an example DX project with function-specific files created for a JavaScript function named `myfunction`:

```ascii
├── functions
│ └── myfunction
│  ├── index.js
│  └── project.toml
│  └── package.json
|  └── README.md
|  └── test
|    └── index.test.js
```

For a step-by-step guide to creating a Functions project, see
[Quick Start](https://developer.salesforce.com/docs/platform/functions/quick-start/quick-start.md).

## Configure Function Dependencies

Each function must provide a list of dependencies that the function must have to build and run. Function dependency information is provided in language-specific configuration files.

### Set JavaScript and TypeScript Dependencies

JavaScript or TypeScript functions specify dependencies and build configuration information in a Node.js `package.json` file in the `<project root>/functions/<function name>/` directory. This file is required to build and run your JavaScript or TypeScript function. For details on the format and fields for a Node.js `package.json` file, see [https://nodejs.org/docs/latest/api/packages.html#nodejs-packagejson-field-definitions](https://nodejs.org/docs/latest/api/packages.html#nodejs-packagejson-field-definitions).

Using `npm install` with the Node.js package.json is recommended when you start developing a function, which installs dependencies to enable things like type support for TypeScript functions code in VS Code. You can also use `npm build` to verify you've added the right set of dependencies.

Generated JavaScript and TypeScript functions include the Salesforce Functions Runtime for Node.js in the `package.json` file:

```json
{
  "name": "myfunction-function",
  "dependencies": {
    "@heroku/sf-fx-runtime-nodejs": "^0.14.0"
  }
}
```

### Set Java Dependencies

Dependencies are defined in your function's `pom.xml` file for use with the Maven build tool. The following `pom.xml` file includes the Salesforce SDK for Java Functions in the list of dependencies:

```xml
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  ...

  <dependencies>
    <dependency>
      <groupId>com.salesforce.functions</groupId>
      <artifactId>sf-fx-sdk-java</artifactId>
      <version>0.5.0-ea</version>
    </dependency>
    ....
  </dependencies>
```

For more information on Maven and `pom.xml` files, see [https://maven.apache.org/](https://maven.apache.org/).

## Configure Function Information in project.toml

Each function must provide a `project.toml` TOML file that contains function metadata. This file usually resides in your `<project root>/functions/<function name>` directory. The `generate:function` command creates a template `project.toml` file that looks something like this:

```toml
[_]
schema-version = "0.2"

[com.salesforce]
schema-version = "0.1"
id = "myfunction"
description = "My Function description"
type = "function"
salesforce-api-version = "56.0"
```

**note:** On creation, `salesforce-api-version` reflects the current version of the Salesforce REST API that the Functions SDK uses. Salesforce Functions supports API version `53.0` or later.

Update this TOML file with any function metadata information you need. For a list of the valid fields for `project.toml` see [Function Metadata TOML Files](https://developer.salesforce.com/docs/platform/functions/guide/toml.md). For details on the general TOML file format, see [toml.io](https://toml.io/en/).

## Include the Appropriate Salesforce SDK

In your function code, import the Salesforce Functions SDK for your programming language.

**note:** When you generate a function with `sf generate function`, these dependencies are included in the example code.

### Use JavaScript and TypeScript

There's no Salesforce Functions SDK required when writing Salesforce Functions code in JavaScript.

In TypeScript, include the Salesforce Functions SDK for Node.js with `import`:

```javascript
import { InvocationEvent, Context, Logger, RecordQueryResult } from "sf-fx-sdk-nodejs";
```

### Use Java SDK Import

In Java, import classes that you need from the `com.salesforce.functions.jvm.sdk` package, for example:

```java
import com.salesforce.functions.jvm.sdk.Context;
import com.salesforce.functions.jvm.sdk.InvocationEvent;
import com.salesforce.functions.jvm.sdk.SalesforceFunction;
```

## Add the Function Entry Point

Functions that access Salesforce data must have a specific code entry point that can be invoked with the invoking org’s context data and payload.

### Specify JavaScript and TypeScript Entry Point

In JavaScript and TypeScript, specify and export a `execute` entry point. The following JavaScript example provides an `execute` entry point function:

```javascript
export default async function execute(event, context, logger) {
  // function code
}
```

The following TypeScript example provides an `execute` entry point function:

```javascript
export default async function execute(
  event: sdk.InvocationEvent,
  context: sdk.Context,
  logger: sdk.Logger,
): Promise<any> {
  // function code
}
```

### Specify Java Entry Point

Java functions must provide a public class that implements the `SalesforceFunction` interface and overrides the public `apply()` method. The following example provides an implementation of `apply()` using `FunctionInput` and `FunctionOutput` classes defined elsewhere in the function project code:

```java
public class ExampleFunction implements SalesforceFunction<FunctionInput, FunctionOutput> {

  @Override
  public FunctionOutput apply(InvocationEvent<FunctionInput> event, Context context)
      throws Exception {

    // Function code
    ...

    return new FunctionOutput(myResultData);
  }
}
```

The types supported for the input and output for SalesforceFunction are specific to the Java SDK and are described in [Java Functions](https://developer.salesforce.com/docs/platform/functions/guide/java-functions.md).

## Add Your Project to GitHub

Salesforce Functions require that source code is tracked with git. When developing a function, add your project to a GitHub repo and push your function code changes regularly to collaborate with other developers. Functions code, unlike Apex code, doesn't get deployed to your org, so you can't use your orgs as a way to share code.

**note:** Function code must be committed to git before you can deploy a function. However, merging your function code to a github.com remote repo isn't required, although generally a good practice.

To add your project to GitHub, navigate to github.com in your browser. Log in to your github.com account, and create a repository. Save the git URL for your new repo. See [Create a Repo](https://docs.github.com/en/github/getting-started-with-github/create-a-repo) for more details.

In the DX project root directory, use the following git commands:

```sh
git init
git add .
git commit -m "Initial project commit after project creation"
git remote add github <git URL for your github.com repo>
```

## Access Salesforce Resources

Connect to additional Salesforce resources using the Salesforce Functions SDK for your language (Node.js or Java). The Salesforce Functions SDKs provide an integrated programming model for writing business logic that connects with your data in the Salesforce Platform.

### Use Context and DataApi

The SDKs provide context data for the calling org when your function is invoked. The data is passed as a parameter to your function entry point. Through this context you can query and execute DML on your org data. Record access is controlled using the Functions permission set in your org.

Through the `context` data you can access the DataApi interface to query, insert, and update records.

The following JavaScript example uses `context.org.dataApi` to make a simple query to the org that invoked the function:

```javascript
export default async function execute(event, context, logger) {
  const query = "SELECT Id, Name FROM Account";
  const results = await context.org.dataApi.query(query);
  logger.info(JSON.stringify(results));

  return results;
}
```

The following Java example uses the DataApi class from the context data to do a query:

```java
import com.salesforce.functions.jvm.sdk.data.Record;

...

List<Record> records =
    context.getOrg().get().getDataApi().query("SELECT Id, Name FROM Account").getRecords();
```

### Discover the UnitOfWork Class

For more complex access, such as complex or large transactions, the Salesforce Functions SDKs provide the `UnitOfWork` class. A `UnitOfWork` represents a set of one or more Salesforce operations that must be done as a single atomic operation. Single atomic operations reduce the number of requests back to the org, and is more efficient when working with larger data volumes. `UnitOfWork` also lets you manage data operations in your own transactions.

The following JavaScript example (from the [Context_UnitOfWork_JS sample](https://github.com/trailheadapps/functions-recipes/tree/main/functions/03_Context_UnitOfWork_JS)) uses a `UnitOfWork` to create an Account record and related records:

```javascript
export default async function (event, context, logger) {
  logger.info(`Invoking unitofworkjs Function with payload ${JSON.stringify(event.data || {})}`);

  // Validate Input
  const payload = event.data;
  validateField("accountName", payload.accountName);
  validateField("lastName", payload.lastName);
  validateField("subject", payload.subject);

  // Create a unit of work that inserts multiple objects.
  const uow = context.org.dataApi.newUnitOfWork();

  // Register a new Account for Creation
  const accountId = uow.registerCreate({
    type: "Account",
    fields: {
      Name: payload.accountName,
    },
  });

  // Register a new Contact for Creation
  const contactId = uow.registerCreate({
    type: "Contact",
    fields: {
      FirstName: payload.firstName,
      LastName: payload.lastName,
      AccountId: accountId, // Get the ReferenceId from previous operation
    },
  });

  // Register a new Case for Creation
  const serviceCaseId = uow.registerCreate({
    type: "Case",
    fields: {
      Subject: payload.subject,
      Description: payload.description,
      Origin: "Web",
      Status: "New",
      AccountId: accountId,
      ContactId: contactId,
    },
  });

  try {
    // Commit the Unit of Work with all the previous registered operations
    const response = await context.org.dataApi.commitUnitOfWork(uow);
    // Construct the result by getting the Id from the successful inserts
    const result = {
      accountId: response.get(accountId).id,
      contactId: response.get(contactId).id,
      caseId: response.get(serviceCaseId).id,
    };
    return result;
  } catch (err) {
    const errorMessage = `Failed to insert record. Root Cause : ${err.message}`;
    logger.error(errorMessage);
    throw new Error(errorMessage);
  }
}
```

**note:** When using the Node.js SDK only, always use a new instance of UnitOfWork for each transaction and never reuse a committed UnitOfWork.

The following Java example (from the [Context_UnitOfWork_Java sample](https://github.com/trailheadapps/functions-recipes/tree/main/functions/03_Context_UnitOfWork_Java)) uses the UnitOfWork class from the Salesforce SDK for Java Functions (with `Input` and `Output` defined elsewhere in the function code):

```java
@Override
public FunctionOutput apply(InvocationEvent<FunctionInput> event, Context context)
    throws Exception {

  String accountName = event.getData().getAccountName();
  String firstName = event.getData().getFirstName();
  String lastName = event.getData().getLastName();
  String subject = event.getData().getSubject();
  String description = event.getData().getDescription();

  DataApi dataApi = context.getOrg().get().getDataApi();

  // Create a Unit of Work that inserts multiple objects
  UnitOfWorkBuilder unitOfWork = dataApi.newUnitOfWorkBuilder();

  // You can use the DataApi to create a Record
  Record account = dataApi.newRecordBuilder("Account").withField("Name", accountName).build();
  // A ReferenceId will be returned to assign relationships with other objects within the same
  // transaction
  ReferenceId accountRefId = unitOfWork.registerCreate(account);

  Record contact =
      dataApi
          .newRecordBuilder("Contact")
          .withField("FirstName", firstName)
          .withField("LastName", lastName)
          .build();
  ReferenceId contactRefId = unitOfWork.registerCreate(contact);

  // Here we are using the accountRefId and contactRefId to specify the relationship with the
  // temporary Id's created by the Unit of Work builder
  Record serviceCase =
      dataApi
          .newRecordBuilder("Case")
          .withField("Subject", subject)
          .withField("Description", description)
          .withField("Origin", "Web")
          .withField("Status", "New")
          .withField("AccountId", accountRefId)
          .withField("ContactId", contactRefId)
          .build();
  ReferenceId serviceCaseRefId = unitOfWork.registerCreate(serviceCase);

  // The transaction will be commited and all the three objects are going to be created. The
  // resulting map contains the Id's of the created objects
  Map<ReferenceId, RecordModificationResult> result =
      dataApi.commitUnitOfWork(unitOfWork.build());

  LOGGER.info("Function successfully commited UoW with {} affected records!", result.size());

  // Construct the result by getting de Id's from the created objects
  return new FunctionOutput(
      result.get(accountRefId).getId(),
      result.get(contactRefId).getId(),
      result.get(serviceCaseRefId).getId());
}
```

UnitOfWork uses the Composite Graph API for efficient transaction requests with higher record limits. For more details on the Composite Graph API see: [REST API Developer Guide: Composite Graphs](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_graph_introduction.htm). Note the [Composite Graph API limits](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_graph_limits.htm), such as a maximum of 15 different nodes or objects or both in one payload, also apply to UnitOfWork.

### Use Salesforce APIs

If the provided SDK classes don't give you the data access you need, you can try making REST API calls directly to the calling org.

In the Salesforce SDK for Node.js Functions, you can use `context.org.dataApi.accessToken` to obtain the API access token for the invoking org. This token can be used with your preferred HTTP request framework to make REST API calls back to the invoking org. You can also use the token to initialize a [JSForce connection](https://jsforce.github.io/start/) to access these APIs:

```javascript
import jsforce from "jsforce";

jsforceConn = new jsforce.Connection({
  accessToken: context.org.dataApi.accessToken,
  instanceUrl: context.org.domainUrl,
  version: context.org.apiVersion,
});
```

In the Salesforce SDK for Java Functions, you can use `DataApi.getAccessToken()` to obtain the API access token for the invoking org. Use your API access token with your preferred HTTP request framework to make REST API calls back to the invoking org.

### Be Aware of API Limits

Most org access from functions is similar to an API request to an org through something like the Salesforce REST API, and has similar limits. See [Limits](https://developer.salesforce.com/docs/platform/functions/guide/limits.md).

### Use Functions Buildpacks and Runtime Environment

The commands `run:function:start` and `project:deploy` use a specific set of [buildpacks](https://devcenter.heroku.com/articles/buildpacks) to build the container image for your function.

<!-- To use custom buildpacks with your function, work with your Salesforce Functions contact to get more details. -->

Deployed functions currently run in the [Heroku-22 environment](https://devcenter.heroku.com/articles/heroku-22-stack).

**tip:** Learn how you can [Use Heroku Data in Functions](https://developer.salesforce.com/docs/platform/functions/guide/heroku-data.md).
