Deploying Serverless Code with Salesforce Functions
Salesforce functions is Salesforce’s variant of serverless compute that utilizes the Heroku stack of compute power to run synchronous and asynchronous functions. The primary benefit to SF Functions is that they are integrated with your Salesforce Org, so you can easily offload any heavy compute processes needed to manage data or perform complex operations, all within the Salesforce trust boundary. The functionality is very similar to Lambda, which I covered how to build and deploy in the SAM Blog Post. This post is a companion post to the SAM one, and I will walk through the similar processes between the two methods, and then another post will follow to compare and contrast some of the differences (User Experience Wise, not technical wise) between the two serverless compute platforms: AWS vs. Heroku/Salesforce. For the purpose of this post though, we will only focus on Salesforce Functions following the guide found in the Salesforce Documentation.
Authentication and Login
You need to have a pretty solid understanding of how Salesforce works in order to get logged in and set up correctly. The most basic “architecture” of the platform you should know is the hierarchy of objects, app, and org.
Org is short for organization, and it refers to a specific instance of Salesforce. A company can have one or multiple orgs, and “scratch orgs” are created as a development instance of an org. Within an Org, there are several apps that are a set of objects, fields, and other functionality that supports a business process for the org. An object is the data that make up the app. To break it down further, an org contains several apps like the “sales” app and “marketing” app, which are then composed of objects such as Contacts, Locations, or Sales.
You need to make sure you have the right dependencies for the sfdx
and sf
CLI’s. There are specific plugins for the sf
CLI required to follow the quick start docs and actually generate and deploy your function. This caused me a lot of headaches to be able to start the basic commands.
The process to auth and set up the project isn’t super straightforward because you need to be able to first: authenticate and log into your Org.
sf login
or sfdx login
Once this is done, you need to enable DevHub, which allows you to create Scratch orgs (A scratch org is a source-driven and disposable deployment of Salesforce code and metadata. You’ll use a scratch org to do your Salesforce Functions development and local testing) and make changes to the Org through the CLI.

Then you also need to authenticate your CLI to the Function App, which is an additional step to authenticate.
sf functions login
There are probably reasons why you can’t just log into your org and have the access you need, but the underlying reason isn’t quite clear to me.
You’ll need to log into a third environment to get all the access you will need. Using sfdx
you’ll log into/create a Devhub User using the following command:
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % sfdx auth:web:login —setdefaultdevhubusername —setalias eth_function_devhub |
So to recap:
- you need to 1. Login to your Org that has the Functions Feature enabled. This is done through the sfdx command:
sf login
or sfdx login
- After you are logged into your org, you will need to authenticate the CLI and login to the Functions account to use the Functions Feature within your Org:
sf functions login
- After you are logged into your org and you’ve authenticated the Functions account/CLI, then you need to log into your Devhub (within the Org) using the following command:
sfdx auth:web:login --setdefaultdevhubusername --setalias [your chosen alias name]
Start Setting Up and Creating
Now locally in your code editor or VS code, you will need to create a project which will auto-populate the applicable files needed for the next steps:
1 | sf generate project -n sf_function_eth |
Once that is set up, you’ll need to create the scratch org (more details provided above). When doing any operation that requires manipulating the actual Org environment, you’ll need to be using the sfdx
CLI commands. You’re also pulling from the newly created /config folder in your directory to generate the scratch org. This is where the function feature is also initiated. In this case to spin up a scratch org the command is then:
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % sfdx force:org:create -s -f config/project-scratch-def.json -a functions_blog_scratch_org |
You can now validate that you have your main Org (with DevHub) and your Scratch Org enabled in your local environment:
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % sfdx force:org:list |
After you’ve created a scratch org, now you need to create a compute environment. A compute environment is where you will actually be running your function and is similar to spinning up a dyno instance in Heroku. This is the final layer you need to build and access to run your function code. You use the sf
CLI command here as you are not altering any Org level data, but rather generating/creating within the scratch org.
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % sf env create compute -o functions_blog_scratch_org -a function_blog_compute_env |
With the compute environment ready, you can now generate your function. Again, sf
is the CLI command here for generation.
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % sf generate function -n blogfunction -l javascript |
Before creating Scratch Orgs for development, please ensure that:
- Enable Functions in your DevHub org
- Add Functions to the “features” list in your scratch org definition JSON file, e.g.
"features": ["Functions"]
This creates a new directory sharing the name of your function (blogfunction
in my case) with your function “infrastructure.” From here, you can edit the index.js
file to begin writing your actual serverless function in Javascript.
Deploying
With your function written, you can now deploy the function code and permissions necessary to run your code in the compute enviornment connected to your Scratch Org.
Deploy permissions to edit Org Data (if needed)
Depending on your functions purpose, you may need to read or write to the Org you’re connected to. In that case, you will need to allow the function to manipulate that data, and that’s done by creating a permission set file in the “force app” directory - which covers the settings within your org. At this path force-app/main/default/permissionsets
, you create the Functions.permissionset-meta.xml
file
1 | <?xml version="1.0" encoding="UTF-8"?> |
You then push this new file to your scratch org to give permissions to the function app to write/create/edit your org data using the sfdx
command since you are pushing an org level change.
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % sfdx force:source:push -f -u functions_blog_scratch_org |
You will then edit your Apex Class file (function_blog_post/force-app/main/default/classes/FunctionApex.cls
) to include the following to receive the invoke command from the CLI, and run the invoked function inside the org You will push this to your org using the same command above.
1 | public with sharing class FunctionApex { |
Deploy your project (containing the function) to the Compute Env.
Now that correct permission is given to the function, you can deploy your function to the compute env associated with that org. Technically, You deploy projects to your compute environment rather than individual Functions. For this guide we’ve created a DX project with a single Function, so we’re only pushing one function.
You need to git commit your changes to the project directory to be able to push to the compute environment. Then you can use the sf
cli to push the project containing the function to the compute environment.
1 | elimchayseng@elimcha-ltmyf5h function_blog_post % git init |
With the above, you can actually see that you just push the commit files to a heroku.com git repository, similar to deploying to a regular Heroku app. The “heroku app name” in this case is your compute environment name. Your code is now deployed.
For Salesforce functions, you can now invoke your code through Apex invoking the function through the Apex Class using the following command:
1 | echo "FunctionApex.test();" | sfdx force:apex:execute -f /dev/stdin |
The results can be logged from the Javascript function and also viewed through the system debugger window in your Salesforce Org. You’ve now successfully built and deployed a function using Salesforce Functions and can perform tasks that interact directly within the Salesforce Trust Boundary of your Org.