Extending Sitecore using serverless architectures
Our universe is expanding, literally. But that also goes for both the Sitecore topology and the Azure stack. In this blog I want to take you on a trip through our Cloud galaxy to show you how you can manage this increased complexity and how you can leverage the potential of these new Azure services in your Sitecore implementations.
We know Cloud is gaining ground and the Azure stack is being adopted more and more — which means the micro-services approach of Sitecore’s architecture that enhances separation of concern, allowing for better maintainability and scalability, could also find its way into our implementations. And on top of that, we have seen that these architectural principles are applicable more than ever, with the announcement of Sitecore SaaS. And the independence of your implementation onto a core product simplifies upgrading too. I think serverless architectures will play an important role in this in the (near) future. So how can we leverage all these new capabilities, stepping away from implementing Sitecore solely from a monolithic perspective? And what are the benefits and caveats of this approach?
In the talk I did on Symposium this year I demonstrated how to build features on top of Sitecore using Functions-as-a-Service (FaaS) and other serverless components, while discussing the use and applicability of such services in our application landscapes.
Our goal is to look past simply deploying Sitecore ‘out of the box’, exploring the use of serverless Azure services, and adopting the Cloud way of thinking when building an application
Our habit is to write software to install on top of the Web App of Sitecore (like Content Delivery and Management roles and xConnect). But you can also extend Sitecore in other ways, which even might fit its architecture better. Sitecore already separates functionality in its architecture and infrastructure. Think xConnect, Sitecore Identity, Cortex and the separate Publishing Service you can install. Also Sitecore Host wonderfully demonstrates that Sitecore is encouraging you to think this way. Additionally, splitting functionality into different services is the perfect opportunity for you to cherry pick what you actually need from Sitecore, and scale up or out the services you use more intensively.
Serverless or FaaS more specifically, is the next level of abstraction in Cloud offerings. There is however an important difference to its predecessors. Where the steps from on premises to IaaS, and then to PaaS, changed the way how we deploy. Going serverless actually changes how we develop. There’s a multitude of tools at your disposal, and as a developer you need to have a good understanding of their architecture, benefits and applicability:
What defines serverless?
Azure Functions is the serverless computing service of Azure that lets you run a class in the Cloud separately, only running it when you need it. But serverless is actually more than only using Functions. It’s the architecture of using multiple micro-service-like technologies, and different storage types, all being fully stateless and solely event-triggered. Those two characteristics are very important and form the base of any serverless architecture.
The benefits of serverless architectures
Some of the most important benefits of this approach to designing applications are:
- Scalability, both up and out, or in terms of cherry picking what you need.
- A higher level of abstraction of functions, leading to better re-use.
- Separation of Concern / Isolation of features, functions and services.
- Releasing packages or functionality separately supports working Agile.
- Functions only run when you need them, saving costs!
Cons of working serverless
However, these features also have a potential downside. Serverless isn’t freeing you from dependencies, it even becomes less apparent to manage, so organization is key:
- Complexity: potential maze of dependencies – be sure to not break compatibility when updating a single node.
- You sometimes experience a bit of latency due to frequent cold starts.
- Requires developers to have notion of resource usage and design.
- Can be more difficult to debug; extensive test automation required.
A serverless demo application
As a demo we’ve built an item history tracker for audit trail purposes. It is not business critical, may operate asynchronously, and is only active when content editors are working. Which is a perfect case for a serverless solution. A simple and small event hook into Sitecore kickstarts the chain of events, using an Azure Function to store this event data in a CosmosDB document. We use another Azure Function to notify SignalR of the update, and a separate Function to handle the SignalR subscriptions of clients. The client, built in Vue.js and hosted in a blob storage container, gets updated instantaneously using this service. You do not have a clue at all this is a serverless application while using it. It really feels snappy.
Additionally, bypassing the SignalR service, one more Azure Function is used to query the CosmosDB database directly, to serve specific selections of data. This whole architecture is what we call serverless, which looks like this:
In this drawing I also pointed out the use of different types of services, like the Azure Functions (Faas), Database Managent, Storage and other supporting services (BaaS) and Integrated Services like SignalR.
Here’s a short video to demonstrate this add-on onto Sitecore:
The services I have used for this demo are an App Service for my Functions, which also automatically creates (or requires) an App Service Plan. This is where I deploy my Functions to from Visual Studio. The CosmosDB contains documents for the leases for the CosmosDB-triggers (to signal updates towards SignalR), and a document for storing my events. The SignalR service is straight forward, no custom configurations there. And lastly (because the logic connector isn’t part of this demo) the Storage Account, with a blob storage containing both the static Vue.js files and the storage required by the Azure Functions:
If you want to have a closer look at the code used for this demo, please go ahead and check out our project. Note that this is experimental code, for demo and research purposes only:
How to extend your PaaS provisioning?
After you’ve created the desired services in the Azure Portal, you should export them to an ARM template. You can do that from the portal, but need to go over the JSON that is outputted to clean it up, remove hard-coded and project specific configurations, and parameterize everything to make the template environment agnostic. When done, you can add this template as an add-on to your Sitecore ARM PaaS provisioning as additional infrastructure.
How to deploy additional Functions?
As seen above, you need to hook into your ‘monolith’ project somewhere, so you partly need to integrate your code into your Sitecore web app deployment. But all the Functions can live in separate projects and can be deployed separately, while still being managed from one VS solution. The best thing though is to split up the build and release pipelines in Azure DevOps, as to not lose the benefit of the flexibility to develop and deploy functions separately.
Five takeaways for effective Cloud usage
Looking back at the journey of discovering new Azure services and serverless capabilities, I must conclude the applicability is far greater than you might expect, as is its ease to use and most of all, the astonishing low resource consumption (we’ve only used up a few bugs a month developing this demo). My lessons learned are:
- Assess & adapt required services and scaling continuously, also when your app is finished and runs in production for a while.
- Utilize the flexibility Cloud gives you, exploring new services and architectures, but also in regard to scaling applications based on time schedules and consumption automatically.
- Think of alternative architectures when extending Sitecore!
- Don’t overdo serverless: complexity = counterproductive. I would not yet build up a whole site implementation in this architecture.
- Conscious resource usage is key, also from your code. Be aware what code triggers which services and how that effects your consumption.
Comments are disabled for this post