A Multi-Tier architecture separates the UI/Presentation, the application and business logic layer, the data access layers, and the database itself in separate applications, potentially running on different computers. In this blog post we’ll examine some of the key traits of this architecture and discuss key reasons for adopting this model.
Multi-tier architectures are fairly common these days and they are becoming even more relevant in today’s mobile world, given the traditional client/server model doesn’t adapt much to lean and remote devices. Multi-tier applications are better suited to accommodate a multi-device world, in which users need to access information from apps running on different devices and different types of connectivity. Multi-tier architectures are certainly not new, but interest in this model keeps growing due to increased use of mobile devices and extended availability of cloud computing.
From One to Three Tiers
In the early days of computing, developers built applications that were running on a single computer. As technology progressed, most non trivial applications migrated towards a client/server architecture. In many cases the server was a database server (or Relational Database Management System: RDBMS), in others it was a server implementing a standard Internet protocol (HTTP, NNTP, SMTP, FTP, …), and occasionally a custom server with a proprietary implementation.
In this blog post, I will focus on data access so let’s consider the client/server scenario. It can be used in two “extreme” modes… with a continuum in between:
- Fat Server Scenario. Have a fat server, with the business logic and data processing implemented in SQL, using views, stored procedures, triggers, and all of the wealth of features a database server provides — and a fairly thin client with only UI rendering of the data and data entry.
- Fat Client Scenario. Have a light server, with tables and little more, and have all of the business logic in the so-called fat client, which generally helps improving the quality of the UI and user experience, given data entry can be driven by the data and logic available at the client.
Why does it matter for this analysis on multi-tier? Because it is exactly that business logic layer that you might want to keep on the server, while you implement it with client technologies (like Delphi, or other programming languages).
In a typical 3 tier scenario, you have the database server with limited customization, an application server that accesses the database, processes the data, and provides data to the client, which is just a thin UI layer. These three logical tiers can be three physical tiers (ie, running on separate hardware) or they can be virtual.
Beyond the 3-Tier Model: Modern Multi-Tier
Over time multi-tier and web services have been implemented with different technologies and communication layers. As an example, RAD Studio’s DataSnap started by using DCOM and TCP/IP, and later migrated to HTTP and REST. Among the various options, the combination of SOAP and XML was the most popular for a few years.
Modern multi-tier architectures, also known as web service architecture or service-oriented architecture (SOA), favors REST/JSON over the older SOAP/XML approach. We also see a trend in app development that moves from single large monolithic services to smaller focused services federated together (generally called micro-services).
Finally, a modern web service architecture tends to follow the HTTP protocol core tenet of being stateless. Each operation is complete in itself and each new operation doesn’t depend on a previous one. This way the services can be distributed flexibly on the physical servers, in multiple redundant copies, for failover and scalability.
Advantages of Modern Multi-Tier
There are so many different ways to define a multi-tier architecture, so I’ll focus on a fairly specific scenario, which is taking a “fat client” client/server application and migrating it towards a REST-based web service.
1. Server-Side Business Logic Provides Easier Updates
It is easier to update an application that has the database access and significant part of the business logic on the server, without having to update the client software that is installed on dozens, hundreds or thousands of client devices. For example, if you want to move to a per-customer discount and need to add extra fields in the database, modify SQL queries, and update a price list that depends on the customer, you can probably do this change without updating the client software used for placing orders. You might have to update only the software used for managing the customers and their discounts. Consider that even popular mobile games these days update the game logic from a central location and are heavily based on web services, with user status and progress saved in a central location, but at times even offering a way to play live and in real time with other players.
2. Faster, More Secure Data Access
Originally, one of the reasons for multi-tier was also to reduce the number of the users licences in the RDBMS, but licensing rules have since changed — so this is rarely relevant these days. Direct database access also causes more dependency on having a proper and updated database client driver (which is not trivial on mobile) and as mentioned above requires a way to update queries in the client application dynamically (or updating the entire client software) as rules and data structures change.
Both for security reasons and performance, unless all of your client applications are on a VPN, granting remote access to the database is generally a security concern. This increases exponentially with clients on mobile devices, using public WiFis or other fairly unsafe scenarios. But even more, direct database access over the Internet is generally slow as the database access protocol are not optimized for low latency and potentially slow and unstable connections. A stateless HTTP access is much more reliable for an Internet and a mobile connection.
3. Better Scalability and Easier Cloud Migration
As your application grows and adds users, you could approach the problem of scalability with mirrored databases and more powerful network infrastructure. This approach requires advanced planning and can become expensive quickly – both in terms of database server licenses and more expensive network services.
Multi-tier architecture offers a less expensive approach through an intermediate tier of web services that absorb some of the network traffic burden. Having additional servers to handle HTTP requests (and any peak in network traffic) is much easier to manage, particularly when deployed to a cloud infrastructure. In other words, migrating a web service architecture to the cloud is generally easier and less expensive, compared to migrating an architecture relying on databases as the primary backend. Even if a database will still be there, if it is not the interface to the clients, this ends up adding flexibility to the system — despite some additional complexity.
4. Separate the Data Access Layer
From the RAD Studio perspective, the migration of a Delphi or C++Builder client/server application to a multi tier model requires taking your data access layer (possibly hosted in data modules) and moving it to the web service side. The same data access layer you are using in client/server (we prefer FireDAC in our apps) can be used in the middle tier. Now depending on how clean is the separation of your data access code to the UI code (your data modules-to-forms coupling) this migration can be simple or require a significant rewrite.
This is an area we could discuss at length, but a general suggestion is to make sure you reconsider and rethink your architecture. What makes sense on a client (for example, caching a lot of data for future use) might not make sense on the web service, specifically if this is a stateless web service discarding any intermediate data after each individual request is completed. Some developers still prefer a fat middle tier (with an ORM or similar rich object models) but this is not always ideal for a web service, because of its stateless approach (you want to limit the data associated to a user or short-lived session) and the need to access the data model concurrently by multiple threads processing multiple requests by different clients.
So why is this data access layer separation an advantage of multi-tier? Rethinking your application architecture will be an effort, but you can reach the goal of having a more modern, flexible, scalable, and performant architecture, compared to what you started from.
In general terms, avoiding the rich database server model reduces your dependency on the server vendor, so you could potentially switch your database back-end. You can achieve this with either a fat client or a web service. The fat client tends to move a lot of data to the user’s machine, while the web service application can run the DB locally and have a huge bandwidth available to access database data.
5. Many Clients, One Service… and Multiple Client Models
A very significant advantage of going towards a multi-tier model these days is the ability to use a single backend service for many different types of client applications. If you have a Windows client/server application today, you can start migrating the Windows applications to the multi-tier model, keeping most of the UI unchanged. Once this is done, you can create mobile or web applications based on the same web service and the same application logic the service already provides.
The mobile clients might be different from the Windows application, and generally “thinner” (less powerful, focused on specific features) but ultimately part of the same application architecture.
6. Caching Data Locally
Adopting this architecture doesn’t mean the data lives only remotely. For example, it often makes sense to build UI rich clients that handle data entry or local data processing for your customers. Also, on mobile platforms you might not always have a good quality connection and you might want to save some of the bandwidth cost to your end users.
In all of these cases, a multi-tier architecture can be augmented by caching some of the database data locally on the client.
This might be done by using simple persistent data structures (like a FireDAC MemTable or a ClientDataSet in RAD Studio) or by embedding a full database on the user device (like the embedded version of InterBase, IBLite — which is free to use for RAD Studio developers).
7. Ability to Build MicroServices and Use Additional Data Conduits
Another advantage of this architecture is the ability to build many web services that work together, rather than a single monolithic piece of software. Individual web services can access different back-end databases, if needed. They can also provide a unified way to access to additional cloud services (for storage, collaboration, and more), without the need for the client to authenticate with all of these services directly. The main advantages are a significant additional security and a way to change some of these services (like moving to a different provider) behind the scenes with no impact on the client application.
One interesting aspect of RAD Server is a single server can load multiple independent runtime packages providing custom APIs. If you have multiple servers, you can combine these APIs freely. But you can also make them all available in a single RAD Server instance if you prefer — while the development can be focused on one module at a time, in isolation.
8. Migrate Versus Rebuild
Some companies think if they want to go to web service architecture they have to start from scratch. We believe that if you have an existing investment in RAD Studio source code, you can leverage it by migrating the existing code to a new architecture. You can also do it in phases, as this is not an all-or-nothing proposition. A phased migration to multi-tier is an significant advantage of this model. For example, you could take a limited subsystem, create a web service for it, build a mobile application using it, and retrofit an existing Windows application to use the web service as well — even if the bulk of the application architecture remains based on client/server.
9. A Better Architecture for Mobile
While you might not be keen on abandoning the fat client/server model for desktop applications, consider that mobile applications have unique challenges:
|Data processing on server, optimized communication from web service to client. Possibly also local caching.
|Limited CPU power
|Use the more powerful server-side for CPU-intensive cycles.
|Intensive CPU data processing negatively affects device battery
|Use the more powerful servers for processing cycles, reducing battery drain.
|Higher Risk of Device Loss and Theft
|Ability to disable an account on the server and block the application, and get users back up running quickly with replacement devices.
|Difficulty Installing and Updating database drivers
|No installation required on the user device (mobile but also desktop).
In Summary, It’s Worth the Effort
Creating multi-tier applications increases the complexity and adds migration work, but is worth the effort. The ability to open your architecture might be critical, if you want your application to remain relevant in the future and avoid falling behind your competition.
By adopting a multi-tier architecture, as I’ve discussed, you gain easier updates, faster and more secure data access, better server scalability, a cleaner data access layer, easier migration to mobile platform, and better integration with other available services.
Want to Learn More?
It’s easy to add multi-tier logic to your Delphi and C++ applications with RAD Server. Explore our RAD Server videos for examples using REST, web clients, and more. The docwiki provides a technical RAD Server reference. For a high level overview of RAD Server, along with deployment license information, visit https://www.embarcadero.com/products/rad-server.
Note: RAD Server deployment licenses are now included in Enterprise and Architect editions of RAD Studio, Delphi and C++Builder, so if you’ve got those editions you can get started immediately, as the development tools are also already in the product.