Introduction
In 1991, Tim Berners-Lee developed the first web browser called World Wide Web and released it to the world. From this humble beginning came a tsunami that reshaped our world in ways that no one could have predicted.
The web browser enabled people from all walks of life to create and consume information from across the globe. This democratization of technology has led to a Cambrian explosion of sorts. Now, anyone can publish content, information, games, community sites, and applications of all types using the browser as a common platform.
One could even say that the web browser is the operating system of the internet. Indeed, Chrome OS has proven that the modern web browser is powerful enough to provide most of the functionality that any user would need. While the internet itself existed long before the browser, it was the browser that enabled everyone to access it.
Today, the browser has become the common system at the heart of the web. Common web standards continue to drive innovation by allowing web applications to experiment with new features and interfaces. We have seen the evolutionary process play out through this dance of competition and collaboration.
Technology has come a long way since 1991. But after decades of building, maintaining, fixing, and architecting web-based solutions, one thing is clear—everything old becomes new again.
While web applications are a specific branch in the broader tree of software development, the basic guidelines and principles behind successful applications have not changed since the foundational beginnings of software development itself. In fact, as complexity has increased, the need for those basic principles has increased as well.
In this report, I attempt to distill over 25 years of experience architecting and building web applications into a series of guiding principles. While I have often acquired this knowledge the hard way (and sometimes at great cost), it is my hope that I can help others learn how to think more holistically about the bigger picture. In other words, take the lessons I’ve learned and avoid those common pitfalls.
Building modern web applications is not only more critical than ever, but also more confusing. With traditional websites, CMS (content management system) sites, SaaS (software as a service) applications, headless technologies, ecommerce, decoupled apps, mobile, etc., there is no end to the ways that technology is reshaping itself over and over.
The good news is that once you learn to identify the successful patterns described in this report, you can apply them to your projects and prevent problems before they begin. Even better, you can also take advantage of positive feedback cycles to deliver better results faster, with fewer mistakes, and with greater ease.
Web-Based Solutions and Challenges
Building web applications often inspires discussions about hybrid versus headless architectures, or unified versus decoupled applications. Popular trends and frameworks usually drive planning. However, while these decisions are important, there is a much more important understanding that must come first.
We must always remember that we are humans, using human-made tools, to create things for the use and enjoyment of other humans. The trickiest issue at the heart of technology is not the technology itself, but the person behind the tool—how they think, work, and feel about the world.
The fundamental challenge facing architects, developers, and IT leaders today is that the default approach to software development is shaped by basic human understanding. This inevitably leads to the same problems over and over again because the instinctive approach to creating in the digital world mirrors how we create in the physical world. By that I mean that people naturally think about building single, monolithic things. Whether that is a chair, a book, or the next great app, we must first imagine the thing we want to create. However, just as in any other form of engineering, we need to apply systems-based thinking and basic guidelines of good design in order to create things that are scalable, sustainable, and reliable.
Successful web development requires a holistic understanding of the application you are designing (internal systems) and how it fits into the broader picture (external systems). Every system creates feedback cycles that have a net result greater than the sum of those parts. Whether that net result is positive or negative depends on how the system is architected and used in operation.
Your problems will rarely be about the technology used. Your primary problem will always be at the human level. It is not the tools, but the mindset that matters, and that is the secret to repeatable success. When you learn to adopt a component-based approach and the mindset of virtuous cycles, you can be successful with any technology. In some cases, you can even be more successful with old, outdated, or discarded tools because your inherent ability is where the value lies.
In this report, we’re focusing on web-based applications that rely on modern browsers as the application framework. However, these general principles for success apply to any form of software development.
In order to break with the pain of the past, we must understand that systems create feedback cycles. These cycles amplify the effects of building and maintaining our applications. Once we understand the difference between virtuous cycles and vicious circles, we can optimize for the results we want.
Vicious Circle Versus Virtuous Cycle
As noted, the default approach to creation tends to focus on a single, monolithic thing apart from the rest of the universe. Often there will be features, requirements, or other acknowledgments that describe the relationship between the thing we are creating and everything else, but these are often secondary considerations.
With a monolithic mindset, everything done to advance or extend the application leads to greater problems like increasing technical debt, bugs, poor performance, and slower delivery times. This is called the vicious circle.
When an application is trapped in the vicious circle, most attempts to extend or improve the project actually only exacerbate the underlying problems. Eventually, the application must be decommissioned or replaced before its time.
By contrast, when we pay attention to proper component-based design, we can create workflows that are optimized for more efficient development. Applications can become faster, more performant, and less error-prone over time. They’re also easier to maintain, and we naturally develop the ability to pay down technical debt or simply avoid it altogether. We call this the virtuous cycle.
The goal is to create applications that can generate the virtuous cycle both within their internal systems as well as within the external systems that they are part of. In order to avoid the vicious circle, we need to understand the primary structures at play and the inherent challenges that come from working with web applications.
Primary Challenges
Most modern web applications are variations on the basic client-server architecture. In the simplest model, the client makes a request from the server, which then returns the requested data to the client. The client then can process that data and make additional requests as needed.
With web applications, the browser is the primary client. However, it often may be making many calls to many servers, and those servers may also be a client making many requests to other servers. These server requests are often organized into “services” or API contracts.
On top of that, the browser is responsible for creating and managing a complex user interface. This means dealing with user interactions, updating itself, and otherwise acting like a proper application should. While the client is often viewed as the “end of the line” in a simplified architecture, a modern web application also acts as an interaction layer itself.
Web applications are based on a collection of different systems that are exposed via interfaces with varying degrees of access and ability. Successful applications are able to manage this complexity reliably and provide patterns that balance the current needs with future possibilities.
The biggest challenge we face is the ever-increasing number of libraries, frameworks, technologies, and services that are intended to solve these problems. As the number of options grows, it becomes difficult to know where to invest in new tools and where to standardize existing ones.
Choosing new technologies and approaches can give us an advantage, but what happens if those things go away? What happens if they fail, or if they don’t scale properly, or if they just don’t deliver on the promise?
On the other hand, what about the risk that comes from the lack of innovation? Falling back on old tools and approaches may be faster in the short term, but it does leave us open to disruption by more modern technologies.
This is the fundamental challenge facing IT leaders and architects today. In order to be successful, we have to find a balance between innovation and tradition. Knowing that technology trends rise and fall, we need to be careful not to adopt new approaches too quickly. At the same time, we need to be bold in our willingness to disrupt ourselves and look for better approaches and tools.
The good news is that successful development and architectural principles are universal. These principles work regardless of the specific technologies or the size of the application in question. They can give us the confidence to adopt or reject new technologies because we know that our applications are resilient.
Creating Virtuous Cycles
So, how can an application be resilient? While it is impossible to be “future proof,” using best practices will allow you to remain “future ready.” The principles that lead to virtuous cycles also put you in a position to make changes in your application without major difficulty.
In fact, when a virtuous cycle exists in an application, the natural tendency is to look for ways to improve, refine, and even disrupt the application from within. The low level of technical debt coupled with a truly composable approach makes experimentation possible, and this is one of the synergistic effects we should expect to see.
The goal of this report is to help you create a virtuous cycle in all your projects. By sharing the guidelines and patterns that make modern web application development successful, we increase the chances of your success and enable you to rapidly evaluate and evolve your tools to meet your organization’s needs. The more you practice the patterns of the virtuous cycle, the easier and more natural it becomes.
This is the key secret: there is no secret. It’s not about modern technology or the latest advances, nor is it about what some other organization has done to be successful. What works for others may not work for you. This is why we focus on the fundamental basics for all successful projects. When this is done, the appropriate architectural decisions will naturally arise.
Instead of being trapped by the static image and a waterfall-based plan, we look at resource flow and efficiency at all levels of the development life cycle. If you design a system that is efficient and productive for all users, then you will win every time. Good choices lead to positive feedback cycles that reinforce successful patterns. The outcome of every successful project is the virtuous cycle.
Before we can talk about how to set up the virtuous cycle, we need to understand its opposite: what leads to the vicious circle, and what trends, patterns, and habits to avoid if you want to stay out of that trap. Once we are able to identify these things, the principles of successful web application development will make sense, and you will understand how to apply them to your own process.