Application architecture explained in-depth with a real-world example
In my previous post on application architecture, I discussed various components that form a scalable web application architecture. That article will help you understand the basic building blocks of application architecture.
Besides explaining the fundamental components, I’ve also designed the bare-bones architecture of a sports news service like ESPN. If you haven’t read it, I suggest reading it first.
In this post, I’ll design and discuss the application architecture of a food delivery service like Swiggy, Zomato or Uber Eats, that’ll give you further insights into the intricacies of application architecture. You’ll get an overview of event-driven architecture, data architecture, etc.
With that being said, let’s get started.
Application architecture of a food delivery service
A food delivery service like Swiggy has several bounded contexts or strategic sections on the backend, such as order management, handling payments, inventory management, onboarding new restaurants and managing them, delivering the orders to the customers (delivery management) and so on. These are all bounded contexts as per the domain-driven design approach.
Besides these domain contexts, the application at the architectural level will have more components, such as the search component, that will enable a user to search through the available restaurants and their menus. A notification component to keep the customers notified of their order status, to keep the delivery person notified of the order status updated by the restaurant, to keep the restaurant notified of the payment status of the order to be delivered and so on.
Naturally, all these functionalities should not be coded in a single monolithic architecture to avoid our codebase from becoming a big ball of mud. We will leverage microservices in our application architecture to keep the system scalable, available and manageable.
Here is the architectural diagram of our application.
Now, let’s understand the request-response flow and the components involved.
Request-response flow in the application architecture
When the customer opens our app, they will send a request to the backend to look for the restaurants and their menu. Since all this data is mostly static, it will be served from the CDN at the edge location. New and updated data and the data that is not present in the CDN will be fetched from the application search service.
When the user selects a certain item and books an order with a certain restaurant, the request is routed to the backend to the order management service via the load balancer and the API gateway built to handle customer requests. The architecture contains multiple API gateways leveraging the backends for frontends pattern. Check out the blog post I’ve written on this for details.
Keeping things simple, I am assuming our service only runs in a certain geographic region. If not, we have to implement global load balancing and then the regional load balancers and distribute our app across several cloud regions and availability zones across the globe.
If you wish to delve deep into the details, I suggest going through the CDN and load balancers article of the system design series I run on this blog.
API Gateways are a gateway for all the traffic hitting the backend, providing secure access to our services via a REST API. Do go through the API gateway article on this blog to get an insight into the significant role API gateways play in our application architecture.
Now, when the request hits the order management service, it triggers events to communicate with other services, such as the payment service, user membership service, delivery management service, inventory service, etc.
The communication between these services happens through events delivered asynchronously to each other via distributed message queues. This architecture style is commonly known as the Event-driven architecture, where application components, as opposed to being tightly coupled with each other, communicate asynchronously via events.
To complete a transaction spanning several microservices, an architectural pattern called the Saga pattern is typically leveraged. If you wish to learn the event-driven architecture, Saga pattern and related concepts, including the fundamentals of web architecture and designing distributed systems, check out the Zero to Software Architect learning track I’ve authored. It takes a deep dive into application architecture right from the bare bones to designing large-scale distributed systems like Netflix, YouTube, ESPN, Medium and more. The learning track covers key topics like databases, how they handle concurrency, intricacies of microservices and related patterns like Saga, event-sourcing etc., application infrastructure, cloud deployment, and a lot more. Check it out.
The application data from various microservices goes into respective databases and the relevant data that has to be made available to the users when searching for food items streams into the search server via the change data capture approach.
The change data capture approach monitors the databases for data changes and based on business rules, pushes the latest data to a message queue to be delivered to different downstream components. In our case, it is the search storage component. The search server manages the search component of the application.
Besides storing data in the search server, all the static data, like images, video files and so on, are also stored in the cloud object storage. You’ll find application infrastructure details in my platform-agnostic cloud computing course. Which is a part of the zero to software architect learning track.
Besides streaming data to the search server via the change data capture, all data from the databases is streamed to the data warehouse and the data lake to run data analytics.
Data analytics in application architecture
Running analytics on the application data helps in two ways:
- It gives deep insight into the application infrastructure. Developers can figure out things like why the app is crashing for certain users. Why is the compute consumption so high for certain services? How many additional servers need to be added to a cluster of a certain service to ensure its availability? and so on.
- It gives business insights, such as why the application’s churn rate so high. What is the average order rate during a certain time interval? How many users subscribed to the annual membership the previous year? What are the projections this year based on current data? and so on.
Data staging area
Data from the databases and cloud storage streams to a staging area through a message queue. The staging area or the staging database is the application component that serves as a temporary storage area before the data streams to a data warehouse.
Since the data streamed from several sources is heterogeneous in nature, it must be prepared before it is streamed to downstream components in a data architecture. The data, after extraction, is transformed into a standard format and structure in the staging area for further processing.
If something amiss happens during the data extraction and transformation, the entire process can be rolled back before polluting the data in the data warehouse.
A data warehouse typically stores large volumes of structured data in a queryable form, acting as a single source of truth for reporting and analysis. The data is optimized in tables for running queries against it. This is done to allow engineers to make sense of massive amounts of data that the application stores over time by running data analytics over it.
I’ve already discussed above how running data analytics is helpful for the business. If it weren’t for the data warehouses, the analytics folks would have to query the production databases of respective microservices for data, possibly making the data inconsistent and error-prone and putting additional load on them.
When working with a data warehouse different enterprise teams like the order management team, payments, restaurant management and inventory management teams have to work with the same data warehouse to run analytics. This may make things complex since the data teams have to deal with is huge.
To make things more manageable, data is split into data marts based on bounded contexts for individual teams to work on. So, we can have an order data mart, payment data mart, inventory data mart and so on. A data mart is a smaller version of a data warehouse containing data typically less than 100 gigabytes.
From the application architecture diagram, we can see that the data from the distributed message queue beside flowing into the staging area also moves into the data lake. Let’s find out what a data lake is.
A data lake stores data in a raw unprocessed form, unlike a data warehouse. This is done in order to get access to raw data immediately or when the purpose of data isn’t determined yet. Getting immediate access to raw data helps in getting real-time insights from the data, unlike the insights from the data warehouse where the data takes some time to reach.
Once the engineers decide how the data has to be dealt with, it can either be moved to the data warehouse or directly to the data compute layer.
Data compute service
The data compute service facilitates running additional compute on data (it may be running machine learning algorithms, data aggregation algorithms, and so on) before being sent to the stakeholders, developers, data scientists, data analytics engineers in the form of organized reports. The component delivering the data reports is known as the data visualization service. Please go through the Grafana and cAdvisor blog posts for details on this. I’ve discussed further details in my course.
Now, let’s hop back up the architecture and have a quick look at the notification service.
A dedicated notification queue is set up to ingest the events required to send notifications to the customer, restaurant and delivery person.
All the services (order, payments, inventory, etc.) push events to the notification event queue, which in turn feeds in the event data to a notification service.
The notification service computes the events and sends apt notifications to the respective receiver in real time. In my distributed systems design course, I’ve designed a notification service which is a standard component in any web application today.
Well, folks. This is pretty much it. I hope you enjoyed reading the article. If you found it helpful, do share it with your network for more reach. You can also subscribe to my newsletter below to get the content delivered to your inbox.
If you wish to delve into application architecture further, you’ll find my Zero to Software Architect learning track immensely helpful. It not only prepares you for the system design interviews but makes you a better software engineer as a whole.
Where to go next?
Check out the blog post on monolithic architecture that takes deep dive into what it is and the use cases involved.
You can read about me here. I’ll see you in the next article. Until then, Cheers!
Zero to Mastering Software Architecture Learning Path - Starting from Zero to Designing Web-Scale Distributed Applications Like a Pro. Check it out.
Master system design for your interviews. Check out this blog post written by me.
Zero to Mastering Software Architecture is a learning path authored by me comprising a series of three courses for software developers, aspiring architects, product managers/owners, engineering managers, IT consultants and anyone looking to get a firm grasp on software architecture, application deployment infrastructure and distributed systems design starting right from zero. Check it out.
- System Design Case Study #5: In-Memory Storage & In-Memory Databases – Storing Application Data In-Memory To Achieve Sub-Second Response Latency
- System Design Case Study #4: How WalkMe Engineering Scaled their Stateful Service Leveraging Pub-Sub Mechanism
- Why Stack Overflow Picked Svelte for their Overflow AI Feature And the Website UI
- A Discussion on Stateless & Stateful Services (Managing User State on the Backend)
- System Design Case Study #3: How Discord Scaled Their Member Update Feature Benchmarking Different Data Structures
CodeCrafters lets you build tools like Redis, Docker, Git and more from the bare bones. With their hands-on courses, you not only gain an in-depth understanding of distributed systems and advanced system design concepts but can also compare your project with the community and then finally navigate the official source code to see how it’s done.
Get 40% off with this link. (Affiliate)
DataCamp offers courses, skill tracks, and career tracks in data science, AI, and machine learning. With interactive exercises, short videos, and coding challenges, learners can master the data and AI skills they need.
With the data engineering courses, you can learn how to design and create the data infrastructure businesses need to scale and master one of the most lucrative skills worldwide. Check out the website here. (Affiliate)