Using Azure Functions in production
I have been working as an interim CTO in a Lean Service Creation agency here in London for the past year and one of the most interesting pieces of work that has come across my desk was to do a full replatforming for a startup in the event space.
They gave me free reign on the technology side to build a futureproof and scalable platform for them. They had grown enough to start having issues with their WordPress-only site and wanted to build a platform to take them to the next level.
They had an interest in working with Microsoft technologies already and combined with my expertise and connections to Microsoft the tech stack was pretty obvious. We went with a cloud-native application on Microsoft Azure built with C# for the backend and a single page webapp with React and Redux for the frontend.
I worked on the architecture and designed a serverless microservices architecture for the system. I chose to go with Microsoft’s serverless offering called Azure Functions as I had previous experience working with Amazon’s serverless counterpart AWS Lambda on building eCommerce-systems and wanted to see what Microsoft had to offer.
We opted for Functions instead of Service Fabric for a few reasons but the main one was cost. It is a lot cheaper to run Functions then a Service Fabric cluster. With Functions you only pay for the time the functions are actually run, not for the idle time.
The serverless/FaaS (Functions as a Service) approach goes well with DDD (Domain Driven Design). It forces you to really think about your system, what the bounded contexts are and how you split into services. Each function is independent with it’s own data store and communicates with other services only asynchronously via message passing. A big no-no for microservices is to have services nicely split per context but then all feeding into a single database. Guess what becomes the bottleneck then. Azure Functions also automatically scales each function as needed and you don’t need to worry about scaling groups. With Functions it is also easy to use CQRS (Command Query Responsibility Segregation). You have separate functions for reading the data from the ones updating data. Reads tend to outweigh writes significantly so it makes sense to separate them so they can be scaled independently of each other.
The architecture ended up as follows:
- RESTful API defined in Swagger which is serves the API-endpoint to clients.
- API is managed in Azure API Management which provides authentication, throttling, access control, transformations, etc.
- Azure Functions written in C# implementing the different services
- API endpoints from API Management mapped to corresponding Azure Functions.
- Each Function/service has it’s own datastore in Azure DocumentDB.
- Azure Search indexes the DocumentDB databases on update triggers and provides search functionality to the data.
- Inter-function communication with Azure Service Bus.
- Separate web frontend as a Single Page App with React/Redux.
Azure Functions was in Preview when we started but was about to come to GA (General Availability) before the launch. We decided to take the gamble with Microsoft promising support, close collaboration and a feedback loop for any issues. We had some minor issues during the development which we worked thru with Microsoft experts' assistance. Big thanks to Microsoft for that.