35 Commits

Author SHA1 Message Date
Renovate Bot
fdeb11e1ef chore(deps): update @types/node to 24.8.1 2025-10-17 04:45:49 +02:00
533f5b0d40 Merge pull request #184 from Mastermindzh/content/what-is-architecture-really
content: what is architecture really - first blog post in a series ab…
2025-10-14 22:55:15 +02:00
1790b2763d chore: updated the date of the latest article to today 2025-10-14 17:21:25 +02:00
d1637ab59b build(package-lock): updated package-lock to be in sync with package.json 2025-10-14 17:08:51 +02:00
b53d579b27 content: what is architecture really - first blog post in a series about software architecture 2025-10-14 17:02:19 +02:00
29d5da925d Merge pull request #183 from Mastermindzh/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to 8.46.1
2025-10-14 16:35:12 +02:00
Renovate Bot
dcce5de7dc chore(deps): update typescript-eslint monorepo to 8.46.1 2025-10-14 12:35:42 +02:00
28523be412 Merge pull request #182 from Mastermindzh/renovate/markdownlint-0.x
chore(deps): update markdownlint to 0.39.0
2025-10-14 11:26:30 +02:00
08ecb725ba Merge pull request #181 from Mastermindzh/renovate/node-24.x-lockfile
chore(deps): update @types/node to 24.7.2
2025-10-14 11:25:26 +02:00
ef9d6902a2 Merge pull request #180 from Mastermindzh/renovate/lint-staged-16.x-lockfile
chore(deps): update lint-staged to 16.2.4
2025-10-14 10:43:03 +02:00
Renovate Bot
7e424489de chore(deps): update markdownlint to 0.39.0 2025-10-13 12:50:07 +02:00
Renovate Bot
6adaef44f1 chore(deps): update @types/node to 24.7.2 2025-10-11 20:46:44 +02:00
Renovate Bot
d0c0e67d1a chore(deps): update lint-staged to 16.2.4 2025-10-11 12:48:36 +02:00
297e55a28b Merge pull request #177 from Mastermindzh/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to 8.46.0
2025-10-10 14:08:28 +02:00
Renovate Bot
b2bebf7ad1 chore(deps): update typescript-eslint monorepo to 8.46.0 2025-10-10 04:45:53 +02:00
47d69ef868 Merge pull request #178 from Mastermindzh/renovate/major-react-monorepo
chore(deps): update eslint-plugin-react-hooks to 7.0.0
2025-10-09 22:40:57 +02:00
62074372cd Merge pull request #179 from Mastermindzh/renovate/node-24.x-lockfile
chore(deps): update @types/node to 24.7.1
2025-10-09 22:38:58 +02:00
Renovate Bot
cd73a8e529 chore(deps): update @types/node to 24.7.1 2025-10-09 20:47:49 +02:00
7ddb11e48b Merge pull request #172 from Mastermindzh/renovate/font-awesome
chore(deps): update font awesome
2025-10-09 09:43:22 +02:00
025267500d Merge pull request #168 from Mastermindzh/renovate/commitlint-monorepo
chore(deps): update commitlint monorepo to 20.1.0
2025-10-09 09:42:18 +02:00
ed7c06ed3a Merge pull request #170 from Mastermindzh/renovate/typescript-5.x-lockfile
chore(deps): update typescript to 5.9.3
2025-10-09 09:41:34 +02:00
Renovate Bot
8bd8bd9c70 chore(deps): update eslint-plugin-react-hooks to 7.0.0 2025-10-09 04:47:20 +02:00
Renovate Bot
587f259793 chore(deps): update font awesome 2025-10-06 20:50:23 +02:00
Renovate Bot
829c5b17b6 chore(deps): update commitlint monorepo to 20.1.0 2025-10-06 20:50:04 +02:00
Renovate Bot
024a145259 chore(deps): update typescript to 5.9.3 2025-10-06 20:49:44 +02:00
4359926604 Merge pull request #169 from Mastermindzh/renovate/node-24.x-lockfile
chore(deps): update @types/node to 24.7.0
2025-10-06 14:23:58 +02:00
72b4c2598e Merge pull request #171 from Mastermindzh/renovate/browserslist-4.x-lockfile
chore(deps): update browserslist to 4.26.3
2025-10-06 14:22:58 +02:00
eacb97ff99 Merge pull request #174 from Mastermindzh/renovate/stylelint-16.x-lockfile
chore(deps): update stylelint to 16.25.0
2025-10-06 14:21:56 +02:00
db38601960 Merge pull request #175 from Mastermindzh/renovate/eslint-monorepo
chore(deps): update eslint monorepo to 9.37.0
2025-10-06 14:21:12 +02:00
339489eb54 Merge pull request #173 from Mastermindzh/renovate/major-react-monorepo
chore(deps): update eslint-plugin-react-hooks to 6.1.1
2025-10-06 13:03:12 +02:00
Renovate Bot
06234dfb46 chore(deps): update @types/node to 24.7.0 2025-10-06 12:50:05 +02:00
Renovate Bot
c902c98e9b chore(deps): update browserslist to 4.26.3 2025-10-06 04:46:07 +02:00
Renovate Bot
38d02cec06 chore(deps): update eslint monorepo to 9.37.0 2025-10-04 04:46:06 +02:00
Renovate Bot
b34d598900 chore(deps): update stylelint to 16.25.0 2025-10-03 20:35:41 +02:00
Renovate Bot
d93a6ada5b chore(deps): update eslint-plugin-react-hooks to 6.1.0 2025-10-02 04:47:00 +02:00
7 changed files with 887 additions and 224 deletions

View File

@@ -1,2 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

View File

@@ -4,6 +4,7 @@
"disqus",
"fontawesome",
"fortawesome",
"frontliners",
"frontmatter",
"gitops",
"homelab",

View File

@@ -0,0 +1,138 @@
---
title: What is Software Architecture (Really)?
date: "2025-10-14"
template: "post"
category: "software-architecture"
tags:
- "software architecture"
- "software development"
- "engineering culture"
- "team dynamics"
- "people management"
- "team maturity"
- "frontliners"
- "adaptability"
description: "Software architecture isnt a fixed design or a set of diagrams, its the evolving set of decisions that guide how a system behaves and grows with its team."
socialImage: ./media/compass.png
---
## A new category on rickvanlieshout.com: Software Architecture
This new category is about the *real* side of software architecture.
Not buzzwords, not picture-perfect diagrams, but the messy, human part of designing systems that actually work.
Ive spent many years working with different kinds of architectures, from tightly coupled monoliths to sprawling microservice landscapes. Along the way, Ive learned that architecture isnt about doing things the “right” way, its about understanding *why* youre doing them in the first place, and how they fit into your team and products reality.
Note that this applies both to enterprise systems as well as open-source initiatives.
## What software architecture actually is
Software architecture is the set of decisions that define how a system behaves, evolves, and is understood over time.
Its not the framework, not the diagram, and not the shiny technology you picked. Its the *reasoning* behind those things, and how they hold up when the system changes.
If software design is about the details, like how classes interact, how APIs are structured, and how code is organized, architecture is about direction.
Its the compass that helps the team navigate change without losing its bearings.
Good architecture provides just enough structure for a team to move fast, without locking them into a corner. Its the scaffolding around the code, the **shared mental model** that keeps complexity in check.
But architecture doesnt exist in isolation. The same design that works beautifully in one place can fail completely in another, which brings us to the one factor most people overlook: **context.**
## Why context always matters
Theres no single best architecture, only architectures that make sense in a specific context.
A perfect design on paper might fail completely when you drop it into the wrong environment. The right architecture depends on your product stage, your constraints, and, most importantly, your team.
At Frontliners, weve seen this up close.
We took on the task of replacing a monolith that had been in production for more than 25 years. It was deeply intertwined with the business, used everywhere, and full of edge cases that only existed because of decades of real-world use.
To make matters worse, these edge cases are often only known to some users, others just "follow what they've been taught".
We didnt have a large or deeply experienced team at the time, but we did have a strong sense of purpose.
We knew we wanted to modernize, to move toward something distributed and scalable, but we also knew we couldnt do it all at once. That meant making tough decisions, again and again, weighing what we could achieve now against what would still make sense later. This is especially true from a technical perspective as during this tumultuous time we've switched both CPO and CEO multiple times. They all offered new and shiny things, and tech was left trying to realize them within increasingly shorter timelines.
We focused on the people we had, their strengths, their limits, their growth potential, and built an architecture that could *grow* with them.
It wasnt perfect, but it gave us some momentum, and that momentum led us to something sustainable.
Still, even with the best intentions, its easy to lose perspective once youve found a path that seems to work. The next challenge we faced wasnt technical at all, it was cultural.
## When good principles turn into dogma
During our early microservices phase, we fell into a trap many teams do.
We started creating “rules” that sounded right, but didnt always fit reality.
Things like *“you can only do X”* or *“you can NEVER depend on another service”*.
And whilst I, as the architect or CTO, never called these "rules" (rather: guidelines), when they were communicated between layers of old <> new developers they often turned into "rules".
Rules like that can be comforting because they feel like control, but theyre often just fear in disguise.
Take something like route calculation. When you have hundreds of parameters and thousands of routes, you cant pre-compute every possible scenario. Sometimes you need to depend on another service, and thats fine. Architecture should adapt to problems, not deny their existence.
The problem wasnt the technology, it mostly never is, it was the mindset.
Without a clear product goal, people cling to certainty. Those “rules” gave us a sense of safety, but they also made change harder. We eventually had to tear those walls down and rebuild our way of thinking, together.
That rebuilding forced us to look inward and ask hard questions about who we were as a team. Because architecture isnt just about systems, its about people.
## Architecture and team maturity: balancing trade-offs
Every architecture exists in the shadow of the team that builds it.
A highly mature, cross-functional team can handle complexity. A newer or smaller team cannot, no matter how good the intentions are.
If your architecture outpaces your teams ability to understand or maintain it, its not a good architecture for you.
Progress sometimes means taking two steps forward and one step back. You might accept a short-term compromise, a “bad” thing, to enable the next leap forward.
And thats okay.
Because architecture isnt a competition, its a conversation. The best systems evolve through collaboration, not commandments.
Let the team make mistakes, learn, and recover. If you enforce every decision from above, youll gain consistency, but lose creativity and ownership.
Every engineer should be part of that conversation. They dont have to think about architecture every day, but they should *care* about it. Curiosity and challenge keep architecture alive.
Yet even with a healthy mindset, time changes everything. The longer a team works in the same system, the easier it becomes to stop questioning it.
## Choice blindness and the value of fresh eyes
As teams settle into a certain way of working, patterns start to feel “normal.”
Pain points fade into the background, awkward workarounds become invisible (even desired!). Over time, everyone forgets that things could be different. I call this *choice blindness*, when familiarity blinds you to your own design decisions.
Thats why new hires are so valuable.
They dont carry the same assumptions. They look at your system and ask the uncomfortable questions:
“Why does this work like that?”
“Is that rule still needed?”
“Has the context changed since we made that decision?”
Sometimes those questions sting. But theyre essential, because context *does* change.
Teams evolve, products evolve, constraints evolve, and what once was a good choice might be holding you back now.
Helping teams see those patterns and guide that evolution is what good architects do best.
## The role of the architect
An architects job therefore isnt to dictate (though they are often given that power), its to clarify.
They connect the big picture to the teams day-to-day, make trade-offs explicit, and keep people aligned. The most valuable skill an architect has isnt technical, its adaptability.
A good architecture isnt static. It bends with the product, the people, and the business.
And that adaptability only exists when the team is part of the conversation.
Architecture thats understood by everyone lasts longer, because it belongs to everyone.
And that shared ownership matters, because architecture isnt something you finish, its something you *continually* shape.
## Architecture is ongoing, not final
Architecture is never done. Its a living process that shifts with each decision, sprint, and release.
That constant evolution can look chaotic from the outside. To stakeholders or customers, it might even seem like were changing direction all the time.
But thats exactly what makes a system resilient, it changes with its context.
You cant plan your way to perfection, you can only *evolve* your way there.
The key is communication. When we explain *why* were making architectural changes, and how they serve the product long-term, that “technical mess” starts to look like healthy adaptation.
A system that never changes is a dead one.
Thats something we learned first-hand. At Frontliners, we saw how both people and systems evolve, and how one without the other simply doesnt work.
## Wrapping up
At Frontliners, we started with a thirty-year-old monolith and a small, still-growing team.
We worked through complexity, limitations, and doubt. We made decisions that werent perfect, but they kept us moving.
Now, we have the right people and the right balance.
Were building something sustainable and great. What helped us wasnt just the technical architecture, but its *ability to change with its context*.
That, to me, is what software architecture really is.
In the next article, well look at how these ideas translate into structure, comparing **monoliths, distributed monoliths, and microservices**, and when each one actually makes sense in the real world.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -7,7 +7,8 @@ import { compilerOptions } from "../../tsconfig.json";
const onCreateWebpackConfig = (
(options: Pick<CompilerOptions, "paths">) =>
({ actions }: CreateWebpackConfigArgs) => {
({ actions, getConfig }: CreateWebpackConfigArgs) => {
// Keep existing TS path aliases in webpack
actions.setWebpackConfig({
resolve: {
alias: Object.entries(options.paths || []).reduce(
@@ -19,6 +20,28 @@ const onCreateWebpackConfig = (
),
},
});
// Workaround: Gatsby's webpack ESLint plugin is incompatible with ESLint v9+ options
// on some environments. Remove the plugin from the webpack pipeline during development
// to prevent build failures like "Invalid Options: Unknown options: extensions, useEslintrc".
// We still keep linting via npm scripts.
try {
const config = getConfig();
if (config?.plugins?.length) {
const beforeCount = config.plugins.length;
config.plugins = config.plugins.filter((plugin: any) => {
const name = plugin?.constructor?.name;
return name !== "ESLintWebpackPlugin" && name !== "ESLintPlugin";
});
const afterCount = config.plugins.length;
// Only replace when we've actually modified the plugins array
if (afterCount !== beforeCount) {
actions.replaceWebpackConfig(config);
}
}
} catch {
// noop if Gatsby changes internals, don't crash the build
}
}
)(compilerOptions);

940
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -128,7 +128,7 @@
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.5.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-hooks": "^7.0.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"globals": "^16.3.0",
"husky": "^9.0.0",
@@ -139,7 +139,7 @@
"jest-svg-transformer": "^1.0.0",
"lint-staged": "^16.1.2",
"lost": "9.0.2",
"markdownlint": "^0.38.0",
"markdownlint": "^0.39.0",
"postcss": "^8.5.6",
"postcss-scss": "^4.0.9",
"prettier": "^3.6.2",
@@ -147,6 +147,7 @@
"react-test-renderer": "^18.3.1",
"rimraf": "^6.0.1",
"sass": "^1.89.2",
"sass-embedded": "^1.93.2",
"source-map-support": "^0.5.21",
"standard-version": "^9.5.0",
"stylelint": "^16.21.1",