Blog

Seeing through objections against full-stack development

By  
Leif Åstrand
Leif Åstrand
·
On Jan 15, 2025 3:04:36 PM
·

Maybe it's just me standing on the top of a hill screaming out to the world about the benefits of full-stack development. Or maybe you're also inspired by the idea but struggling to convince your customer, manager, or other colleagues? Many of the common objections against the concept are based on taking certain things for granted, whereas a different mindset will reveal things in a different light.

As a reminder from my previous post, I define a full-stack web application as an application that offers the same kind of highly interactive user interface that we're used to from SPAs but built as a single application, including both the frontend and the backend. Keeping everything in a single application helps avoid redundant code, but more importantly, it also leads to less multi-tasking and coordination overhead between separate teams.

In this article, we’ll cover:

A photo of a developer coding on a laptop, with an IDE visibly open on the screen.

Choose the right amount of separation

There was a widely criticized code example a while ago in the presentation that introduced React Server Actions to the world. It showed a button click listener that started with a "use server" declaration and then went on to construct and execute a SQL query from within the same code block. This is a very powerful way of explaining the concept, and I might have done similar things in unpublished prototypes, but it's not the way to build maintainable applications.

Direct access to every part of the stack can be very powerful. With great power comes great responsibility. Just because you can traverse the full stack from some user interaction to the database in a single callback doesn't mean that you should. Proper separation of concerns helps keep the spaghetti monster away. Just don't over-separate by building frontend and backend as two separate applications! You want to have loose coupling, not lousy coupling. The same separation mechanisms that help keep SQL out of your business logic will also inoculate you against SQL in click listeners.

The simplest way is to simply draw a line in the sand by documenting where the SQL belongs. If you (or your eager colleagues) keep forgetting this recommendation, then you can use a tool like ArchUnit or Spring Modulith to enforce the rule. If you want even stricter separation, then there's also the possibility of structuring your application as a multi-module project. Just note that this can and should still be a single application. It's deployed as a single unit, stored in a single source code repository, and developed by a single team.

A separate application is not needed to keep SQL out of business logic, so why would the frontend have to be treated differently?

Full-stack team members work together

One might mistakenly think that full-stack development is done by full-stack developers. While that might indeed be the case, a more universal definition is that full-stack development is done by developers in full-stack teams. I'll put them next to each other to make the distinction absolutely crystal clear: full-stack developers vs developers in full-stack teams. It's the team as a whole that is full-stack, while individual developers can specialize in different parts of that stack.

In particular, a full-stack architecture doesn't mean that every team member must be a pure-blooded full-stack developer who is fed React for breakfast and Spring for lunch. Diverse members of the team will happily work together to build the application in a way that most efficiently utilizes everyone's skills. This is the case not only for frontend and backend but also for, e.g., UI design or DevOps – every team member doesn't have to be an expert in everything that the team does. All those specializations can further be supported by tools that reduce the cognitive load in that area. In the case of full-stack development, it is a development platform such as Vaadin.

We developers are curious creatures. We want to learn about new things to expand our toolbelt to cover more potential situations. The vast majority of frontend or backend developers I’ve spoken with are open to exploring the other side, as long as they have someone from the "Baywatch" team to rescue them if they venture too far into unfamiliar waters. Each part that the team takes care of can have additional support from outside the team. There can be a platform team for DevOps, DBAs, and enterprise architects for the backend, and a design system team for frontend development.

Watch our recent webinar on the future of full-stack development for insights into team collaboration and overcoming common challenges.

Another client is not an excuse to treat the first client poorly

The third common objection I hear comes into play when the application must support third-party clients. Or, when it might possibly need to happen at some point in a distant, hypothetical future—maybe. This can be a completely valid requirement, but it can also be a magnificent source of premature optimization. It might be tempting to treat the application's primary web-based UI as one standalone client out of many. I guess you already know what I have to say about building the frontend as a standalone application that is separated from the backend…

The value of a dedicated data access layer for the web UI

Building a dedicated data access layer for your web UI is an investment that is quickly paid back.

REST endpoints and other similar logic are typically a relatively small part of the codebase. A development framework with good support for a full-stack architecture will further simplify the way data is made available specifically for the web UI. And you guessed it! Vaadin doesn't build just one such framework, but there are actually two of them: Vaadin Flow and Hilla.

Web UI updates can be deployed almost immediately. This gives simpler API evolution compared to third-party REST clients that might update very infrequently, if ever. Most of the functionality in, e.g., JAX-RS or Spring's @RestController exists precisely to give full control over API evolution. Rejecting that complexity makes it much faster to iterate the UI design and how it interacts with your backend logic.

A dedicated data layer improves performance since you can tailor server-side data aggregation to meet the web UI’s exact requirements. If your backend is based on microservices, you can simply create an additional service that consumes data from the other services and makes them available in a format tailored specifically for the web UI.

Your web UI is not just another REST client

Let’s be clear: your web UI should not be treated as just another REST client. If that is the case, then you shouldn't build a UI; instead, just teach your users how to use Swagger or RESTMan. A REST API is overly generic so that it can support every possible use case, whereas a web UI is based on a single UI design. It might be tempting to reduce duplication by reusing the existing REST for the web UI as well. But that's like eliminating redundant keystrokes when coding by reusing the same generic variable names everywhere. As we’d say in many parts of Europe: cent wise, euro foolish.

Still not the silver bullet we have been waiting for 

We still need to be careful in our ideological campaign toward the light, as there are certainly cases where a full-stack application might not be the best option. Only an ignorant fool would believe that there is a single approach that applies to all situations. However, anyone arguing against full-stack development should find other justifications than achieving separation, saving developers from learning, or supporting other clients.

No matter if you agree or disagree, let your perspective be known in the Vaadin forum.

Leif Åstrand
Leif Åstrand
Leif Åstrand keeps an eye on the overall architecture of the Vaadin platform. He knows a thing or two about how Vaadin, Web Components, and the internet works.
Other posts by Leif Åstrand