It will be 10 years ago next month that I wrote my first line of Apex code. Visualforce was in beta (though not yet packageable), the only valid use of the “extends” keyword in Apex was for custom exceptions, and S-Controls were still alive and kicking… happy days.
Earlier in 2007, and of slightly (British understatement) more significance than my first Apex trigger handler, Heroku was founded.
By 2009 my trigger handler class now belonged to a FinancialForce product, and in the same year Heroku had commercially launched as a deployment platform for Ruby apps.
In 2010 Salesforce acquired Heroku, then in the following year Heroku added support for Node.js, Clojure, Java, Python and Scala. The acquisition of Heroku by Salesforce was interesting. Heroku and the Lightning Platform or “the platform formerly known as Force.com”, are very different beasts.
The Lightning Platform is a high productivity Application Platform as a Service (aPaaS) designed for “power admins” and “citizen developers” and is primarily model-driven – based around Salesforce Objects (SObjects). Apex, Visualforce and Lightning Components provide coding capabilities for advanced requirements, but this is a “low-code” platform in technology and culture.
Heroku on the other hand is a high-control Platform as a Service (PaaS) designed for developers, and which firmly embraces a message-driven architecture. We might call it a “high-code” platform, designed to be elastically scalable to very high throughputs.
It was a few years before we saw any real bridge between Heroku and the Lightning Platform. Heroku Connect was introduced in 2014 as an automated data synchronisation service which is often used by freestanding Heroku web apps or services to bring data into Salesforce without the Heroku developer knowing too much about the Lighting Platform.
Lighting Platform apps have become bigger and much more complex, to the point where “low-code” is perhaps no longer a very good description of what is going on. Apex governors are a “one size fits all” way of managing platform resources, and may well be suited to a “low-code” platform. However with the very complex logic now being written in Apex, governors are driving engineers to extreme lengths to get the job done.
Some Apex developers have looked enviously at the Heroku environment which not only offers computational power which can be scaled up to the needs of the task, but the ability to choose the most suitable language, and the availability of a plethora of libraries and frameworks which mean that the developer need not reinvent the wheel on a daily basis.
Some intrepid developers have decided to straddle the gap between the Lighting Platform and Heroku to take advantage of Heroku compute power within their applications – embedding Heroku power within their Salesforce applications.
However, despite the advantages of using Heroku compute with the Lightning Platform there are challenges to be overcome.
Identification and Authentication
When starting a Heroku compute process from within the Lighting Platform, your Heroku process will most likely want to check the identity of the caller – the Salesforce Organization and User – and whether the Org Admin has authorised the user to perform the action.
Similarly, when the Heroku process needs to call back into the Lightning Platform, Salesforce will likewise need to authenticate the request and identify the Salesforce User – and Heroku will need to provide the necessary credentials. This ensures that the data written back to Salesforce is tied to an appropriate Salesforce user – which will often be the user who initiated the process.
To a large extent, Heroku’s scalability comes from the way it can handle processes asynchronously – using a message-driven architecture. Ok, so you don’t have to write asynchronous services in Heroku, but you’ll be limiting your application’s scalability if you don’t. Worker Dynos, Background Jobs and Queueing does a good job of explaining this, but here’s a real world illustration:
Imagine you walk into a pizza place, you make your order and the person who takes it pops on an apron, washes their hands and heads back into the kitchen to prepare your food. What happens to the next person who comes in? There’s no one to take their order! That’s synchronous processing. There’s a lot of waiting. I want to get my order taken right away, and maybe step next door to pick up some gelato while my pizza is being prepared. Maybe I’ll pop in to ask how it’s going – or better yet get a notification on my phone when my order ready.
With asynchronous processing, work is put into a queue. In Heroku if the queue gets too long, then you can either increase the power available for your process, or use a greater number of “processors” to get through the work faster. Either way you are not causing anything upstream to wait while the work is done.
The downside of running asynchronous processes is that it involves a different way of looking at the implementation and a little more effort – publishing and subscribing messages to a queue, and considering how you’re going to respond to the process ending.
FinancialForce has recently released the Orizuru open-source toolkit to help to overcome these challenges.
For Identification and Authentication there’s a package which makes the necessary calls to the Salesforce Identity Provider, to validate the requests coming from Salesforce, and also to authenticate with Salesforce in order to call back in when needed. There’s also a command line tool which configures both the Salesforce org (with a Connected App) and the Heroku app – wiring up the authentication both ways.
With the asynchronous processing side of things, Orizuru aims to make this as simple as writing Batch Apex. You, the developer, write the code that does the actual work you want done in Heroku – maybe pulling in some super libraries in Node or Java, and the Orizuru toolkit does the plumbing: Apex API client, API service, validation of requests, publishing messages to a queue and subscribing from the queue.
It’s early days, so there are bound to be some gaps, but it’s an open source project, and the team would welcome both constructive criticism and contributions!