Why We Develop Using Language Stacks, Not Languages.

Zdeněk Brabec
Omio Engineering
Published in
5 min readJan 28, 2022

--

In 2022, virtually every company is a tech company. At least in some sense. Many have a whole arsenal of developers building and maintaining software of myriad varieties. Mobile applications, presentation websites, admin panels, backend systems, core infrastructure, automation jobs — the whole gamut, really. It’s genuinely difficult to imagine companies functioning without software anymore.

If one sits with the sheer scope of that for a moment, one inevitably comes face to face with the realization that… that’s a lot of technology. There are mobile apps written in Java and Swift, websites in javascript/html/css, and backend systems in one of the hundreds of general-purpose backend languages. And that’s just scratching the surface, really. Just taking as granted that all this software-dependency involves a lot of data, one then has to imagine how that’s managed. Data engineers love Python. So, on top of all the other programming languages at work, Python gets added to the mix.

There are many, many more technologies and languages driving all this, depending on the product (for instance, we haven’t even broached game development or systems programming, here). Most languages come with a set of varying frameworks. A framework is a third-party managed library; a sort of shorthand that allows developers to do common tasks more efficiently. So when we talk about a plethora of programming languages at play in what companies are doing, we’re also talking about the fact that each of them has a number of associated frameworks. And there’s a diversity of opinion about how these are best applied, where they offer solutions (and where they don’t), and methodology generally.

That makes hiring very hard, because you need to hire a different expert for each language and framework combination.

Microservice architecture has made this even more complicated. The ability to have every piece of software in a different language is nice, but it’s a double-edged sword. Having a large number of different technologies running simultaneously can quickly become overwhelming for a company, especially with no plan for maintaining all of them. In turn, companies have to settle on a few languages to work with. And not just languages but language stacks.

What’s in a name?

A language stack is a set of integrated technologies that developers use to efficiently create maintainable software, tailored to the company’s best practices. In effect, it’s a programming language with a framework, combined with company-specific configuration and various enhancements; a sort of Swiss Army Knife built around the company’s unique needs.

Typically, a language stack’s implementation is coordinated by a team tasked with managing it. They’re responsible for establishing clear leadership and inter-company processes to ensure that the agreed-upon language stacks are used across the whole organization. A critical piece of that is generating and maintaining consensus around methodology; how language stacks are applied to particular processes, structures, and problems.

That’s a complex task, inasmuch as these aren’t questions with right or wrong answers. Take logging, a standard feature of any organization’s tech. Logging can be done any number of ways, each of them with advantages and drawbacks depending on an organization’s needs. The language stack applied to a given case should dictate which logging library is used, how a log entry should be structured, and where it should be sent. Those rules should be automatically verified and enforced as a part of Pull Request checks or pipeline automation. That could be a preconfigured linter ensuring that all microservices within a language stack follow the same code formatting, or it could involve some other approach entirely.

At Omio, we have currently several language stacks in use — one each for backend systems (java, golang, nodejs), data, frontend, and mobile apps. There is a narrow use case for each of these. Our frontend language stack consists of company-specific react components, tooling for artifact building and deployment, linter configuration, libraries for translations, and so on. The backend language stack comes with an established design method for APIs, how API documentation is created, and how routing, deployment, CI/CD pipeline, logging, and monitoring are done.

Language Stack vs. Framework

Java has Spring, php has Laravel, javascript has reactjs. Those are frameworks that focus on solving a general problem — Render DOM, serve websites, etc. Those are usually open-source, maintained by third parties. A language stack is similar but it’s customized specifically for the company’s use case, and tackles multiple problems or needs simultaneously. At the same time, a language stack can (and should) leverage existing frameworks.

Comparative Advantages

Language stack is built for the whole lifecycle of software development, and comes with all the necessary tooling a developer needs to work effectively and follow best practices. That offers significant advantages for security and maintainability, and provides a clearer overview of what’s happening across teams. It’s easier for developers from a given team to contribute to another code base if that code base follows the same structure and practices as theirs. It’s also much easier to identify potential security issues when vulnerabilities become apparent if all codebases have the same dependencies.

Language stacks also make onboarding new engineers much more streamlined. For a variety of reasons, documentation of best practices should be centrally accessible, whenever possible. Language stacks make that simple. They can be housed in a single repository or multiple repositories, where new engineers can easily track down necessary documentation, making for smoother transition and integration.

Maintaining Language Stacks

A language stack should be maintained by a group of experienced developers within the company. What that governance structure looks like is less important than maintaining efficiency in establishing consensus about practices. That needn’t be complicated. Regular communication between the language stack users can convey improvements and proposals to those tasked with maintaining the process. All aspects should be regularly audited and verified: dependencies should be updated, licenses should be verified and outdated practices should be phased out.

Language stacks also simplify and expedite bootstrapping new projects. A developer can scaffold a new repository in a matter of seconds, working from a predefined structure with all the necessary tooling built in.

In Closing

There’s an old saying that goes, when you’ve got a hammer, everything looks like a nail. The technology it invokes is a primitive one, but its thesis is arguably more relevant than ever. Tools can condition our attention to the problems we’re trying to solve, and not always for the better. At the end of the day, we’re still tasked with assessing the world we’re addressing (and the problems it presents), and making what are ultimately creative, responsive decisions. That’s not a binary proposition; categorically “correct” solutions are negligibly rare. Not every need is strictly technical, and if nothing else, assessing the scope of needs in a given situation is a human task.

Using language stacks to manage tech allows us to work backward from that assessment. It allows for blending tools that balance our unique needs not just efficiently, but elegantly.

Want to learn more? Come join us! We’re hiring for a number of roles, and would love to talk to you.

--

--