This is the first in an ongoing series from developers expressing their opinions on various topics in the software engineering and computer science world. The opinions expressed here are solely those of the author. If you disagree, drop a comment and let us know your take—respectfully, of course.
I suspect that a lot of people will interpret this article as “gatekeeping.” Although I can understand that perspective, I’ve strived to provide an honest outlook that reflects my experience over the last few years (mostly startups). I also want to explicitly disclaim that I will be focusing on fullstack in a web development context. I fully support the notion of a fullstack engineer who has never written a line of HTML or CSS, they are simply not the focus of this article. Without further ado:
If there’s one thing that nobody in the developer ecosystem can agree on, it’s what constitutes a fullstack engineer. Over the last year of teaching myself webdev, I’ve encountered many myths and learned a lot of things about fullstack development.
What's a Fullstack?
Let’s start with a generic, definitely-not-controversial definition of a fullstack engineer:
"Individual responsible for engineering the end-to-end features of a system. From initial user experience to backend code running on distributed servers."
If you have criticisms about this definition, good. That's because, fullstack engineering isn't a real thing. There is no scientific model that describes what fullstack is. There’s no way to measure if one person is more of a fullstack engineer than someone else.The only consensus regarding fullstack is that nobody agrees what it is. This should also make it clear that anything else you read in this article is inherently opinion.
Why is Fullstack so Romanticized?
Even though there isn't consensus regarding what a fullstack is, everyone seems to agree it's something they want. In their defense, the notion of fullstack is very enticing, and it has nothing to do with programming. Fullstack is exciting because it addresses one of the most unavoidable problems when building complex things:
"No matter how well you can separately build parts for something, the overhead of integration is almost always non-zero."
Integration can mean a lot of things, but at a minimum it includes the communication required by the components to fit together. In theory, a fullstack engineer reduces integration overhead to nearly 0, as they control the separate components and therefore only need to communicate with themselves. While communication isn’t the only aspect of integration, in my experience, communication tends to be the bottleneck. With this understanding of fullstack engineering, a single person can potentially be more productive than two, three, or even four people (assuming the integration overhead is non-negligible). Especially from a business perspective, the potential to pay one person slightly more to do a job that previously took four is captivating.
I wanted to create a simple model for a fullstack engineer based on the popular (moreso average) opinion. After reading over a lot of different opinions online, I arrived at the following generalized definition of a fullstack engineer. A fullstack engineer is any engineer capable of executing the entire process of building an end-to-end web experience. I’ve created a model below, which formalizes my interpretation of popular opinion:
A Minimum Viable Fullstack Engineer (MVFE):
- Uses version control
- Knows HTML
- Knows CSS
- Has a strong grasp of programming fundamentals
- Understands distributed systems
- Knows at least one primary backend language (probably NodeJS, PHP, or Java)
- Is skilled with at least one datastore/database
This definition immediately raises some questions such as:
- Does it include testing?
- Does it include design?
- Does it include ops?
At first it may seem like these skills are not necessary for daily life as a fullstack engineer. But remember, the value of fullstack comes from expected reduction in integration overhead. Even though ops isn’t the same as development, there is shared surface area where the two are required to be aware of each other. A fullstack engineer might be able to get by without understanding infrastructure and cloud architecture at the level of the devops team, but if they can’t speak a common language, their potential value begins to diminish. If it isn’t already clear, this notion extends far beyond ops. It includes any aspect of the system (or product process) which the fullstack engineer is responsible for and that needs to be integrated.
Where Popular Opinion Falls Short
It's my experience that the above MVFE is pretty uncommon. The profile describes a person with skills requiring thousands of hours to master, but who doesn’t take part in the holistic decision making process. By nature, the value of a fullstack engineer stems from their ability to make competent unilateral decisions (decisions without asking anyone for permission). I'm sure there are people who mostly fit the MVFE, but I wager that they are few and far between. You could probably summarize my view about the MVFE as:
It's very impractical to become a fullstack engineer without understanding the big picture.
In my mind, a fullstack engineer’s value is mostly derived from their ability to single-handedly design, architect, execute, and operate an entire end-to-end system. Assuming this is possible, it almost completely eliminates integration overhead.
The Reality of Fullstack Engineering
Just to be clear, npm enabled the webdev ecosystem to flourish and grow in a way that few technologies have. That doesn't mean we should be ignorant to its cost, and there is a cost.
A Practical Profile of a Fullstack Engineer
Now that we’re on the same page regarding the goals and implications of fullstack engineering, it’s time to propose a profile for a more realistic fullstack engineer. The goal of this model is to address the concerns I had with the “Popular Opinion” profile, specifically in regards to area of potential integration.
Realistically Viable Fullstack Engineer (RVFE):
All things listed in the "Minimum Viable (MVFE)" profile.
Rationale: All of the items listed in the MVFE are basic requirements for building a modern web application. It may be possible to build websites if you’re lacking skills in the MVFE, but definitely not web applications.
Understands business and customer needs.
Rationale: In a traditional team, understanding needs and subsequently translating those into deliverables usually falls on the product org. While it’s possible to build something you don’t personally understand the value of, it directly impacts your ability to make quick judgement calls and decisions about that thing. On the other hand, if you’re building something that you do genuinely identify with, or at least understand, you’ll be equipped to make empathetic and pragmatic decisions. In my fullstack model, every place where you have to integrate externally reduces your effectiveness. If you don’t understand the customer needs and business value, you will need to be integrating all the time.
Understands role of marketing and how it co-exists with engineering.
Rationale: There are a few aspects of this specific item. I’m not alleging that you need to be a marketing guru to do fullstack, just that you need to understand how engineering and marketing co-exist. Specifically, you should understand the importance and role of analytics and be familiar with the process of integrating services like Google Analytics into the frontend of your site. There’s countless places where marketing and engineering are required to play nice Here’s just a few:
Implementing and reporting on A/B and Canary testing
Integrating sales funnel concepts such as conversions, impressions, call to action (CTA), etc. into the product
Understanding how page design, layout, and responsiveness impacts the above concepts
Has strong project and time management.
Rationale: If it wasn’t already clear, self sufficiency is a fundamental aspect of fullstack engineering. Although the potential benefit of self sufficiency is huge, it also comes with some unfortunate realities. One of those realities is that the more you’re responsible for, the harder it will be for others to manage your time for you. This one especially rings true for me, as I know quite a few people who would be really brilliant fullstack engineers. But because they lack the self-discipline and time management skills, it’s probably not something that would work out for them.
Project management is crucial because it’s one of the most clear and concise ways of communicating with your team. It makes you accountable and gives your managers, partners, and other interested parties visibility into your progress. Last but obviously not least, it forces you to plan and structure your work. Even if you don’t follow a development methodology, you should still be planning everything ahead of time.
Has a solid grasp of design (at least enough to work with designers)
Rationale: Design is so integral to the fullstack process that I could almost argue that fullstack engineers should at least be mediocre designers. At a minimum, a fullstack engineer should be comfortable with modern design practices and tooling. The less you know about design as a fullstack developer, the better you should be at translating design requirements/specs into the exact specified outcome. This is why I actually think it’s easier to just learn design as a fullstack developer, as it gives you a lot more leeway during development to make compromises. Remember, you don’t need to be an artist to learn design. Even just understanding the basics of typography, color theory, and spacing will go a LONG way.
Can design, architect and implement end-to-end software systems.
Rationale: If there’s any aspect of fullstack that people can agree on, it’s that fullstack engineers write software. I would argue that every developer (fullstack or otherwise) should strive to understand the logic they are implementing and not just going through the motions.
Furthermore, many fullstack engineers will struggle with visibility. If you adopt a proper architecture process, it will make it much easier for others to see your intentions without reading the source code. It’s ties directly into time/project management as proper architecting is also explicit planning.
Is familiar with CSS best practices, modern additions, and libraries.
Rationale: This goes hand in hand with the design requirement. At a minimum, you should be comfortable enough with CSS to deterministically translate any practical design mockup into a scalable and functioning representation. The more familiar you are with CSS, the easier your life will be.
For the most part, learning CSS is just memorizing a bunch of keywords. There are a few concepts, such as flexbox and grid, which you should become incredibly familiar with. Basically any website (a responsive one at that) in the world can be built with either flex or grid. I’d also recommend being comfortable with Bootstrap and Material design libraries. They can often increase development velocity, and many employers give you points for knowing them.
Knows at least one single-page application framework (SPA)(and if only one, it has to be React)
Rationale: “Commenters on this post”:
I too, wish I could live on a commune where we grow all of our own food and provide our own resources. Unfortunately, I live in the Bay Area and rent is expensive. While communes might be okay throwing out frameworks, if you plan/need to work at a company doing frontend/fullstack or anything in between, you’ll probably be using React. Even if you aren’t going to be using React, the person interviewing you knows React and that’s more than enough to get you the job.
There are obviously a ton of problems with the current JS ecosystem, especially around frameworks and dependencies. That being said, I’m not going to cut off my nose to spite my face. Problems with the ecosystem aside, I don’t even want to go back to writing vanilla HTML (for the same reason I don’t want to write web apps in ASM). Also, I’d love to hear someone explain why server-side templating is any better than a SPA? Other than performance (because it’s almost a non-issue in 2019 with modern devices), I feel that people just like server-side templating because it’s what they’re used to. As someone who came into this space recently, the SPA route is way friendlier.
Familiar with domain specific frontend concepts (HTTP, CORS, etc.)
Rationale: This is true for fullstack and frontend engineers. I guess you could theoretically write frontends that never communicate to a server, but that would be a pretty boring life. Aside from request/responses, there’s a bunch of other domain specific cruft you should know. It’s honestly silly that modern implementations haven’t abstracted this nonsense away, most of the time you don’t need to touch it.
Has strong SQL and NoSQL skills.
Rationale: After building a reasonable number of fullstack apps, you will assuredly encounter situations where a single data storage model is simply not enough. Although I’ve been thoroughly impressed to see how much some engineers will abuse NoSQL databases to avoid using a relational alternative. In nearly all of those cases, it ended up being more work for the engineers and far more complex than the relational alternative. There are a lot of dogmatic opinions on SQL vs. NoSQL, and the honest reality is that they are both important and have their place. Don’t let not understanding get in the way of making the right decision for your circumstances.
Comfortable with devops.
Rationale: With the majority of modern applications, where and how the application runs can have a huge impact on the way the app is architected. I’ve met with quite a few fullstack engineers who believed they should be completely disconnected from ops. Although this is a nice fantasy, in reality, engineering and ops are inherently intertwined. More than that, not being able to bridge the two either limits what you can potentially build or makes what you build a potential mess.
Depending on what type of fullstack application is being built, knowing the ops might be as simple as understanding the implications that running on Firebase has on your code. For example, in Firebase you might use firebase.config() instead of process.env. I would classify this level of understanding as ‘ops aware’, which basically means you might not be able to do the ops yourself, but you understand the implications of the choices that are made. At a minimum, a fullstack dev should be ops aware. Although, I would argue that it’s very difficult to be a reliable fullstack engineer and not be at least at a junior devops level. It would be very difficult to correctly architect a distributed application if you don’t know what the scaling policies are for the server it will be running on.
Experienced with testing at all levels (unit, integration, end-to-end, UI, stress, A/B, Blue-Green, Canary)
Rationale: If a fullstack engineer is expected to own the application software, they either need to be involved in the testing, or there won’t be testing. Even if you have the most amazing testing team alive, there is no way they can quickly and effectively test an application that nobody explains to them. For this reason, fullstack engineers should at least be comfortable explaining the behavior of the system in a context relevant to the testing team. Practically speaking, if the fullstack engineer isn’t at least writing the unit tests, you probably already lost a lot of value from the fullstack engineer anyway. If they aren’t writing them, it either means other engineers had to spend the time to understand the code and then write tests (thereby reducing the value of the fullstack engineer) or there weren't any tests at all. Obviously both options are bad.
At the end of the day, each and every person is going to have a slightly different definition of fullstack engineering. Even if we could get the whole world to agree, there would be a new term just as ambiguous the next day. The profile proposed above is a product of my personal experiences and what I’ve learned from others. I would love to hear criticism about aspects that people disagree with so I can continue to improve my understanding.