How to manage feature flags in ASP.NET Core apps with Azure?
No matter how simple or complex an application is, choosing the right configuration provider right at the start will mak...
You might be asking yourself how to get from a blank piece of paper to those complex systems you’ve just learned about. Let me share with you an approach that will help you with that.
Before I get to actual architecture, I want to spend a moment to stress the importance of adopting the right mindset before you start moving around those rectangles and arrows.
Many projects have faced troubles or even failed because the design decisions were made with a technology-focused mindset. Your design decisions shouldn’t be driven by technology popularity, desire to play with some shiny toys, or learning a new concept.
Every design decision should be driven by a business requirement. You should sit down with business to capture both, functional and non-functional requirements.
Functional requirements will allow you to architect your solution, so it does the right thing. They will also allow you to decompose by workload. When I say workload, I mean a specific capability or task which is separated from others. It is very common for different workloads to utilize different architectural concepts.
Non-functional requirements will allow you to complete your architecture by addressing aspects like availability, scalability, and costs.
Do you remember that feeling of being overwhelmed I’ve mentioned at the beginning? It comes from the fact that everyone is showcasing and describing final solutions.
But believe me when I say that no one has started there, and neither should you. You should select your first workload and focus on it.
How it can be designed in the PaaS model?
I’m going to assume that your first workload isn’t an edge case, which requires a special architecture approach. That all you need is the web-based frontend and some processing capabilities.
The simplest way to achieve that could be a single N-tier application hosted in Azure App Service, but that would be an oversimplification. You want to separate the layers, which will give you the freedom to further evolve your design.
So, the simplest, yet designed evolution approach would be to have a static fronted, an API, a queue, and a worker service.
The API will be receiving all client requests. Those which require a significant number of resources or have long-running nature will be offloaded to the worker through the queue (which will provide load balancing and load leveling).
To make this architecture a reality, we need to map it to the right PaaS managed services.
For the majority of components in this first workload architecture, there is more than one option when it comes to managed services we can choose from.
I won’t be able to go into all the nuances possible for every option, but I will focus on key questions and the most typical choices.
To choose the database, you must decide if you need a relational or non-relational one.
If your data will be highly normalized, you require and want to enforce the schema, you need high integrity and strong consistency, then you will need a relational database. If you do need a relational database, then the most typical choice will be Azure SQL Database.
If you can go for a non-relational database, you should look in the direction of Azure Cosmos DB.
When it comes to options for computing services on which you should place your worker, I would suggest Azure Functions or Azure Container Instances.
If the processes are short-lived or fit Durable Functions orchestration, choose Azure Functions. Otherwise, go for Azure Container Instances which will give you PaaS hosting for containers.
One more place where you will need to choose between two options is the queue.
Azure Service Bus provides more sophisticated capabilities like sessions, transactions, duplicate detection, and dead-lettering. This makes it the typical choice.
But if you don’t need any of those capabilities, Azure Queue Storage can be a simpler alternative.
The approach I would recommend for the last two components is placing API on Azure Functions and hosting the static frontend in blob storage.
The design of your workload now has the services to do the right thing, now you must ensure it does those things well.
If you have gathered the nonfunctional requirements, you probably have a long list to satisfy with the most common one being:
That list starts with SLAs and SLOs around availability and performance. If you go to specific managed services documentation, you will see their numbers there.
For example, the monthly availability for Cosmos DB is 99.99% without availability zones, 99.995% with availability zones, and 99.999% for multiple regions configuration. Based on input from your business you will know which option to choose. Similar consideration goes for latency.
If the requirements are beyond what service provides out of the box, you will have to adjust your architecture for example by introducing Azure Cache for Redis in front of the database and Azure CDN for your static content.
Of course, all the options described above have consequences and those consequences usually come in form of higher costs.
If you are adding more services to your design, you are increasing the price for the entire system. If you are choosing deployment options that provide higher availability, the monthly price for that service will be higher.
Business should provide you with costs requirements as well. To validate your design against them, you can use Azure Pricing Calculator. It will estimate your monthly costs based on the types of resources and foreseen consumption.
In case when the estimated cost is too high, you will have options to adjust or go back to the business discussions.
Now you can grow your design by adding more workloads. For every one of those workloads, you will have to make the same decisions to ensure that each one of them utilizes the cloud in the right way.
I don’t know if you have noticed, but your architecture is becoming quite complex. It might be time to visualize it better. Here I would strongly suggest the C4 model.
In this model, every one of your workloads can be represented through the separate component diagram, while the container diagram will give you an overview of all workloads. This will allow you to assess the current solution as a whole and plan what is next.
The pattern I’ve shown you is very flexible.
So flexible, that it will be able to handle things it shouldn’t. You need to keep that in mind, so you won’t fall into the one-size-fits-all trap. There will be workloads that will have special needs and there are special architecture styles waiting to be used in such cases.
If you are facing the challenge of analysis and reporting over huge data sets, you should look at big data solutions.
If you are going to run simulations or modeling, you may need to apply a high-performance computing approach.
If you have an IoT workload in your solution, you will want to look at an event-driven approach, which is great for processing a large volume of data at very low latency or when you want to perform different types of processing on the same event.
Always make sure you are using the right style for the job.
I’ve shown you how you can approach designing your solution, but the job of cloud architect doesn’t end with the first diagram.
As much as being agile and embracing DevOps practices is crucial for solution delivery, it’s also crucial to have an agile approach to its architecture.
You need to constantly reevaluate your decisions, make adjustments, and adapt to changing conditions.
The quality of your initial design will have as much impact on the project’s success as your capability to evolve it over time.
Read similar articles