An Introduction to Salesforce Functions
Salesforce Functions, first launched under the nickname “Evergreen”, was released on March 1st, 2022. This new feature gives unprecedented access to the Salesforce platform’s functionality by allowing developers to write code in their preferred programming language. What makes Functions special is the fact that your code is executed in a distinct and safe computing environment – not in your org, therefore not counting against your Salesforce request limits.
What are Salesforce Functions, and why would you use them?
Salesforce Functions let you use industry-standard programming languages and frameworks. You may choose between your favorite languages (although JavaScript, TypeScript, and Java are the only supported languages as of now) instead of having to write or rewrite code in a Salesforce-specific language, saving you development time and effort.
You can excel in your advancements using Salesforce Functions by making it easy to execute complex business logic that was previously impractical. Complexity could have played a role in this (i.e. exceeding governor limits), perhaps personal capabilities (especially if you’re new to Salesforce development), or even the fact that what you wanted to do couldn’t be done in Apex (i.e. manipulating files).
Salesforce functions might have reminded you of Lambda functions or similar – and you’re not entirely wrong! Why would you use Salesforce Functions instead of other Functions as a Service (FaaS) providers?
In short, Salesforce designed Functions to be as simple and straightforward to use as possible. You don’t have to be concerned about network access issues, authentication, or integrating back into Salesforce via libraries. Salesforce takes care of them all without a hitch, allowing you to concentrate on creating code.
How to set up Salesforce functions
This process might seem to be a little tricky if you’re doing it for the first time, so bear with me.
Creating a DX project and connecting to it
The first thing that you should do is register on Salesforce’s functions webpage: https://functions.salesforce.com/signups. After completing the form, within a few minutes, you should receive an email confirming the creation of your account.
After, you should check that you have the latest version of SFDX, as it will come in handy when creating our scratch org and using the Functions commands.
Next, in your org, go to Setup and enter Functions in the Quick Find box and select Functions. Make sure to Enable Test Space and Production Space.
It is recommended to have the appropriate Salesforce permissions. You may check out the required ones in the references section.
For authentication purposes, confirm that Dev Hub is enabled.
You can create a new Salesforce DX project with the following command:
sf generate project - MyFunctionProject
This will create a project directory structure, containing the base project configuration and scratch definition files, important for defining how our scratch will be created.
Once you have created your first Functions project, it is time to connect to your Dev Hub and Salesforce Functions.
To log in and set an Alias to your dev hub, enter:
sf login -v -a MyDevHubAlias -d
And to login to Salesforce Functions,
sf login functions
This will open a browser page where you can log in to your Salesforce Functions account. You need to use the same credentials you used to connect your Dev Hub org.
The next thing you should do is to create a Scratch Org. For convenience purposes, use scratch orgs created from your Dev Hub org to test Salesforce data access. To create it, first, edit the config/project-scratch-def.json in your DX project. Under settings, add the following JSON code:
"functionsSettings": {
"orgName": "Acme Company",
"edition": "Developer",
"features": ["Functions"]
},
Now we can use the updated project-scratch-def.json file to create a Functions scratch org with the following command:
sfdx force:org:create -s -f config/project-scratch-def.json -a MyScratchOrgAlias
This process might take a while. After creating the scratch org, create a Salesforce compute environment associated with that org with this command:
sf env create compute -o MyOrgAlias -a MyComputeEnv # use your scratch org alias
Creating a function and deploying
After having gone through all these steps, it’s time to create your first function. Run this command in the project root directory, where -n is the name of the function and -l your chosen programming language (remember – JavaScript, TypeScript or Java):
sf generate function -n myfunction -l javascript
Your project has now the basic scaffolding for your function, including supporting metadata and default boilerplate code. You may see an index.js file – it is the primary source code file. Edit it to update your function as you like!
Before deploying your function, commit your code changes to a git repo. If you do not have one created, follow these commands:
git init
git add .
git commit -m “Initial project commit after project creation”.
Now, to deploy your project’s function, use the following command with the scratch org alias we created before. It may take some time. Meanwhile, if you wish to check the status of your deployed project, use sf env list.
sf deploy functions -o MyOrgAlias
Deploying Permission Set
It is crucial to update permission sets to ensure that the function we created can access data in our desired Salesforce org. To update the Functions permission set, which is automatically created by Salesforce when connecting your org to Functions, add the file force-app/main/default/permissionsets/Functions.permissionset-meta.xml with the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<hasActivationRequired>true</hasActivationRequired>
<label>Functions</label>
<objectPermissions>
<allowCreate>true</allowCreate>
<allowDelete>false</allowDelete>
<allowEdit>true</allowEdit>
<allowRead>true</allowRead>
<modifyAllRecords>false</modifyAllRecords>
<object>Account</object>
<viewAllRecords>false</viewAllRecords>
</objectPermissions>
</PermissionSet>
You may now use the command force:source:push -f -u MyOrgAlias to push your changes to the Functions permission set of your org.
Testing a Function Locally
As we all know, testing before deploying is very recommended in the Salesforce ecosystem. Functions are not an exception – you should definitely test them in your local environment before deploying them to a compute environment. Head to the function directory and run the following command to run your function:
sf run function start.
As soon as you see the message Starting myfunction, your function is ready to start receiving requests. It keeps running in the background until you decide to stop the execution with the key combination Ctrl + c or cmd + c if you’re on macOS.
To invoke the function, send it to a JSON payload. Create a payload.json file in your function directory and paste the following code:
{
"name": "MyAccount",
"accountNumber": "123456789",
"industry": "Technology",
"type": "Prospect",
"website": "www.salesforce.com"
}
Now, head back to your project root directory and invoke the function (which, if you didn’t stop it, should be running in your local host):
sf run function -l http://localhost:8080 -p '@functions/myfunction/payload.json'
If everything went right, you should see the output as a JSON file – something along the lines of this:
Using defaultusername MyScratchOrgAlias login credential to initialize context
POST http://localhost:8080... 200
{
"done": true,
"totalSize": 1,
"records": [
{
"type": "Account",
"fields": {
"id": "00163000012fAD0AAM",
"isdeleted": false,
"masterrecordid": null,
"name": "MyAccount-1623718504016",
...fields omitted...
"yearstarted": null,
"sicdesc": null,
"dandbcompanyid": null,
"operatinghoursid": null
}
}
]
}
Example
We are going to showcase a Salesforce Function recipes example coded with our programming language of choice, JavaScript. In this model, called DataApiQuery, an account and contacts are returned according to the search of a keyword. The code starts with a logger, displaying the payload of the event. Then, it states that the keyword must be a string – otherwise, an error is displayed. The results are waiting for a query to be executed, returning the Id, Name from the Account, and Name and Email from Contacts where they match with the specified keyword by the user.
Salesforce Functions Recipes
If you received a Salesforce Functions trial org, you should be able to see different demos made by Salesforce Developers, called “Functions Recipes”. Although some previous configuration is required prior to using them, it is completely worth it if you are looking to understand to the maximum depth how Functions work and how useful they can be. I highly recommend checking out the following link and going through the instructions to set them up.
Languages Supported
As mentioned in the previous sections, Salesforce provides support for JavaScript, TypeScript, and Java. Here are some considerations taken from Salesforce’s official documentation, to keep in mind while developing our loved Functions:
JavaScript and TypeScript Functions
- Use the Salesforce SDK for Node.js Functions:
- Set and Access Environment Variables
- Utilize Logs
Java Functions
- Use the Salesforce SDK for Java Functions
- Use SalesforceFunction Input and Output Types
- Use the Java Extension Pack for VS Code
For more information and considerations regarding Java Functions, please check out the references section.
Salesforce Functions Limits
No matter how perfect and handy Salesforce Functions may sound, they need to have Limits. We all know that our CRM is ruled by governor limits, and functions are not an exception. Whether the function is executed synchronously or asynchronously affects these limits. Salesforce official Documentation divides limits into different categories, which are the following:
Time-based limits
Requests from functions to the Salesforce org:
- The number of requests made across all functions and back against an org.
- 235,000 per Function License per 24 hours
- If passing this limit, function calls will fail.
- Execution time:
- How a function run time is tracked, based on memory consumption and runtime duration.
- 1 million GB-seconds per Functions License per month.
- Worth noting: Any overages will incur charges.
Runtime limits
These will be categorized into Synchronous and Asynchronous, just as we mentioned previously.
Runtime
- Synchronous: 2 minutes
- Asynchronous: 15 minutes
Invocation payload size
- Synchronous: 6 MB
- Asynchronous: 12MB
Returned response size
- Synchronous: 6 MB
- Asynchronous: 12MB
Simultaneous invocations
- Synchronous: only 10 long-running (running for more than five seconds)
- Asynchronous: No limits
For additional Limits regarding Apex code and APIs that are relevant to your functions, check out the following links:
Best Practices
In order to develop the best Functions possible, we list below some best practices recommended by the official Salesforce documentation.
- Note Function Invocation Run Time: Run time for Salesforce function varies depending on factors such as dependencies, complexity, and payload. This variability means that your functions may not complete in the same order they were invoked.
- Stay Within Process Memory Limits. Remember that there is a 1GB limit for process memory for each function container, automatically increased or decreased to handle invocations based on CPU load. Each container can handle multiple concurrent invocations.
- Track Function State Across Invocations: Salesforce Functions run in a stateless model, meaning that nothing automatically persists from invocation to invocation. If you do need to persist information across multiple invocations, store it in a file somewhere outside of memory.
- Prevent Out of Memory Errors: Follow the following safe practices to say within memory limits when developing your functions.
- Keep functions simple and focused on a task that can be completed quickly
- Deploy functions with only the essential libraries.
- Profile response times when connecting to external services from functions such as Heroku, Mulesoft, and Slack.
- Test functions to know average execution time and memory use per invocation.
- Test functions in a development environment with payloads similar to production to make sure response time is acceptable.
Summary
To conclude, through this article we have covered the basics of Salesforce Functions, discovering how simple, swifter and efficient they can be. Unlike other external FaaS, Salesforce Functions can be a great way to develop securely in environments like Salesforce. Although only three programming languages are supported as of now, this already opens many possibilities and interesting use cases you can implement and develop. Now that you’re no longer tied to develop with Apex, possibilities are boundless!
References
https://developer.salesforce.com/docs/platform/functions/guide/configure_your_org.html
https://developer.salesforce.com/docs/platform/functions/guide/java-functions.html
https://www.salesforceben.com/get-started-with-salesforce-functions/
https://developer.salesforce.com/docs/platform/functions/guide/index.html
https://github.com/trailheadapps/functions-recipes/tree/trial/1.1/trial-config
https://developer.salesforce.com/docs/platform/functions/overview
No Comments
Sorry, the comment form is closed at this time.