Using Microsoft Orleans: Why?
Introduction
The explosion of Software-as-a-Service (SaaS) over the last two decades created new challenges for the industry professionals tasked with creating and maintaining those systems. When building online applications, large or small, teams must face several decisions that will have long term impacts on the design. Data storage, user patterns, and other “big decisions” will follow (or haunt) the team through the life of the application.
For businesses that were early to the internet, many of these decisions have already been made for them - for better or for worse – in their legacy codebases. For new applications, developers can choose other paths, but the number of options for foundational components has exploded just as the SaaS scene has. Most businesses recognize that the cloud is the future and are already working to progress along any of the common “cloud maturity models” that exist today, but all of those models end in one place: “cloud-native” greenfield builds (or rebuilds) of microservice architectures.
Microservices architectures, themselves, introduce new challenges. Data distribution, concurrency, eventual consistency, and other “hard” patterns point to the need for teams that are highly trained and skilled. Hiring new developers with microservices design experience or creating internal training programs for existing developers can help teams move forward, but both options can be expensive and slow.
Expensive, slow, and hard are not words that excite a business; especially one that’s growing quickly. How, then, do we make that last step to cloud-native software without these downsides?
Microsoft’s Orleans framework is an excellent answer to this complicated question. Suitable for both small and large applications, Orleans solves many of these hard problems in a single, unified framework that allows teams to concentrate on delivering business value over boilerplate or foundational code.
History of Orleans
Orleans was originally built and by Microsoft Research in the late 2000s in response to the demand for hyperscale services to handle the then-new wave of multiplayer Xbox games. Initially deployed as the back-end for Halo 4, Microsoft now uses Orleans in Azure, Xbox, Skype, Halo, PlayFab, Gears of War, and many other internal services. Visa and Honeywell also write applications based on Orleans.
The first publicly available version of Orleans was 2.0, released in 2011 as Open Source software (using the MIT license). Since that time, Orleans has added new functionality, gotten easier to use, and received significant performance updates.
How does it work?
An early decision facing teams is the adoption of an application framework, and most of them can be placed into 2 groups: low-code or high-code. Low-code systems provide huge productivity gains, because you don’t have to write as much code, but are generally less flexible in terms of app capabilities. High-code systems provide the opposite characteristics: more code & more flexibility.
Orleans sits in a sweet spot between the two larger groups because it provides a “strongly opinionated” framework that eases sophisticated development while preserving your team’s existing skill investments in .NET. Additionally, because the team already understands the underlying technologies, it’s possible to color outside the lines if the need arises. That said, you probably won’t need to, since Orleans is a very complete offering.
What does Orleans do for you?
Orleans is a deep framework that provides several major integrated components that dev teams would normally need to figure out for themselves. The vocabulary of Orleans centers around “Grains” and “Silos”. Grains are the encapsulated “virtual actors” that represent business logic, state persistence, and more. And silos are the clustered hosts that serve grain data to the grain client. Together, these represent the core functional structures within Orleans.
Data Storage
Orleans contains a flexible state persistence engine that can transparently save and retrieve grain state using a variety of backing data stores. This includes official support for:
Relational databases via ADO.NET (giving you access to Oracle, MSSQL, MySQL, PostgreSQL, SQLite, IBM Db2, Sybase ASE, and more)
Document databases like Cosmos Db, DynamoDb, and Redis
Blob storage – both Azure Storage and AWS S3
It is also possible to do heterogenous storage, putting some grain data in a document Db while other data lives in a relational store or as a blob. Lastly, if you have other needs, Orleans gives you the ability to implement custom providers via the IStorageProvider interface.
Remote Processing
At their heart, even if an app is doing Event Sourcing, CQRS, or other performance optimization patterns, most SaaS apps are still N-Tier Architectures that have a user client, a front end, a logic/processing layer, and a data store. Commonly, the front end (the REST or GraphQL API) and logic/processing layer, while logically separated in code, are still executing on the same compute resources. Orleans changes that paradigm.
While you can co-host the Orleans silo in the same application as the front end, it is also possible to split them into 2 separate applications running in separate compute pools. This gives several advantages like increased isolation of logic processes, ability to scale domain execution without scaling the front end apps, and additional resilience; when running separately, Orleans can create a fault tolerant cluster of silos to ensure your app stays up.
Caching
Keeping frequently accessed data in a fast cache is an important part of ensuring that your front end supplies data for the best user experience possible. With Orleans, distributed in-memory caching is a core feature that you don’t have to worry about. The automatic grain activation and deactivation cycle ensures that frequently accessed data remains in the silo’s memory for efficient use. Additionally, this memory cache is distributed for resilience and performance. Each grain only resides in only one silo at any given time and the silos communicate with each other to find requested grains. This extremely sophisticated feature is “for free” in Orleans. There is no configuration, development, or other work necessary to take advantage of it. It is simply the way Orleans works.
Command Queueing
Another “hard problem” to solve in SaaS applications is the handling of simultaneous access. What do you do if two users want to manipulate the same data at the same time? There are different ways to deal with this issue, but one of the most common in use today is utilizing Kafka/EventHub command queueing to ensure single-threaded execution against individual domain entities. This can be a powerful architecture for creating apps with lots of simultaneous data access.
Orleans, again, gives you this “for free”. Every grain is fed by a command queue that receives, caches, and executes grain commands in order, providing you thread-safe state changes to your grains’ data. Like caching, there is no configuration, development, or other work necessary to take advantage of this extremely sophisticated pattern. It is, again, simply the way Orleans works.
How does Orleans compare with other similar offerings?
Being a very complete framework, there are plenty of frameworks that do parts of what Orleans does, but only a small few that are true competitors. Two other frameworks that perform similar functions are Akka and Dapr.
Comparing them, we see a lot of similarities in core functionality, but there are several critical differences that would suggest that Orleans is a better choice for many solutions.
Dapr, for example, isn’t exactly a development framework. Instead, it is a run-time that you host in a separate container from your core application. You then integrate with Dapr to provide the required functionality. The big advantage here, however, is that you can use any language to create an app on top of it.
Akka, which is much more like Orleans, features both Java, Scala, and .NET versions, but has fewer “automatic” features (like actor state recovery) than Orleans. While you’d be able to receive many of the same benefits as Orleans, you’d likely end up writing more code to do so. However, with the primary version written in Java, you have access to a rich set of other tools that also run in the JVM.
How will Orleans scale with my business?
Interestingly, Orleans isn’t a technology that is suitable for only the very small or very large business needs. It easily scales from POC to early product iterations through growth phase and can support hyperscale apps, too.
The implications of this kind of scalability are huge. You will, ultimately, throw away less code on your way up the ladder. Less code thrown away means less new code to write. Less new code to write means increased delivery of business value and higher ROI on your development efforts.
Is Orleans ready for primetime?
At Infonuncio Consulting, we’ve implemented these “hard patterns”, like command queueing and caching, in the past using bespoke code. We almost certainly would have used Orleans for those projects if it had been in the state it’s in today. In the last few years, we’ve put Orleans to use in several domains. In FinTech, we used Orleans as the core of a high-throughput transaction switch. In a Social Media app, Orleans represented more than 70% of domain concepts within the application. In a backend for an iPhone game, Orleans was used for the whole implementation. It’s flexible, easy to use, and powerful.
Let’s Talk Orleans
Whether you’re building a new application in .NET or updating an existing one, Orleans is an excellent choice. It gracefully solves many of the hard problems in modern SaaS development and can be a powerful, flexible tool in your portfolio.
Interested in learning more? Let Infonuncio Consulting help you understand how Orleans can accelerate your teams’ delivery of business value. Visit us at www.infonuncio.com and schedule a chat!