Kore Nordmann
@kores-blog@nordmann.name
-
Most complaints about remote work are about things that are either solved or were never real. Clear those away and there is a smaller set of things that do not work remotely. Pretending a video call fixes them is how remote-first loses the people it could have kept.
-
When you start hearing "we can't deliver because of another team" on a regular basis, something has already gone wrong. Usually you have optimised each team's own velocity so hard that you killed the company's. The work that would fix it, one team unblocking another, is invisible to every metric you are using, so it quietly stops.
-
The Sidecar That Shouldn't Exist
Data mesh gives every data product a sidecar: the logical home of cross-cutting concerns like policy enforcement, audit, and quality. I tried to find the sidecar a place in our repository and concluded it must not have one. Some architecture concepts are useful as vocabulary, not as structure, and telling the two apart is a design decision of its own.
-
The Layer Nobody Should Have to Import
My book describes an architecture in one sentence: Controller → Service → Gateway → Storage. It never says what to put in the HTTP box. I published the thing I have been putting there for fifteen years, mostly so I stop copying it between projects, and writing down why it is shaped like that turned out to be the interesting part. A framework should be the dependency almost none of your code imports.
Read more on my blog: The Layer Nobody Should Have to Import
-
Visible Actions Are More Important than Speech
I have watched a manager give a speech about a value and then, in the next small meeting, act exactly against it. People notice. They read what you do as the real message and treat what you say as noise on top of it, and they replicate the behaviour, not the speech.
Read more on my blog: Visible Actions Are More Important than Speech
-
Leaving DigitalOcean Took One Day
I have been a happy DigitalOcean customer for years: stable, simple, never a surprise. Then they put three million dollars into DHH's Omarchy, and I moved everything to Hetzner. The interesting part is not the outrage, it is that leaving took one day and almost no thought, because the whole setup is infrastructure as code. Being able to walk away from a provider on principle is something you build long before you need it.
-
A lot of managers want to be friends with the people who report to them. It does not work, and worse, it is dishonest, because there is a power imbalance everyone in the room already feels. Being kind is not the same as being friends. Pretending otherwise is the actual unkindness.
-
Designing a dbt Pipeline for Consent Withdrawal
When a student withdraws consent, their data must disappear from our learning-analytics platform. Irreversibly anonymised statistics may legally remain. Making both true at once is an architecture problem, not a cleanup script: two strictly separated lanes through the warehouse, a dependency rule between them, and materialization choices driven by deletion semantics instead of query performance.
Read more on my blog: Designing a dbt Pipeline for Consent Withdrawal
-
How to Guarantee You Never Ship
I have written a run of posts arguing against multi-repo layouts, long-lived feature branches, reflexive microservices, dedicated QA, blanket coverage targets, and pull-request review. Each is bad on its own. Stack them together and you get something worse than the sum: a machine, built entirely from respectable best practices, optimised to make delivering a single change impossible.
-
I watched a team write a careful test suite for a feature, then kill the feature two weeks later because nobody wanted it. The tests were wasted effort, and worse: they made the feature harder to kill. How much you should test is not a constant. It moves with where you are on the road to product market fit.
-
A Boolean PII Flag Is Not Enough
Every data catalog lets you tag a column as PII, true or false. For a platform processing student data under GDPR this single bit drops the questions a data protection officer actually asks: Does the column identify on its own or in combination? Is it raw, pseudonymised, or anonymised? Did a human assert the classification, or did a tool infer it? We classify on two axes plus provenance and propagate the result through lineage.
-
Dan McKinley's "Choose Boring Technology" gives you a budget of innovation tokens to spend on novel choices. I agree with all of it, and I want to refine one thing: a token is not denominated in how novel the technology looks from the outside. It is denominated in what your team already knows.
-
Hexagonal Architecture vs. Microservices
Bounded contexts deserve boundaries. But a boundary is a code concern, and putting a network between two contexts because you want them separate is a mistake. In-process interfaces are far easier to debug and to keep consistent than network ones, for a concrete reason: one compiler spans both sides and will not let them drift. Nothing spans the network.
Read more on my blog: Hexagonal Architecture vs. Microservices
-
Why 3D Software Visualisation Keeps Failing
A zoomable 3D scene of your architecture, with domains as planes, services as boxes, and data flows as glowing particles, demos beautifully, and WebGL makes it a weekend project. But 3D software visualisation never failed for technical reasons. It fails for perceptual ones, and those have not changed: occlusion, an arbitrary Z axis, label degradation, and depth being one of the weakest visual encodings we know of.
Read more on my blog: Why 3D Software Visualisation Keeps Failing
-
A while ago I promised to write more about feature flags. Here it is, as one flat rule: develop on main, and use feature flags. Long-lived feature branches are a problem you create for yourself, and most of the structural contortions teams adopt to cope with merge hell are there to solve a process problem with architecture.
-
I made this argument to my team again last week, while a neighbouring team was busy splitting their monorepo into around eighty repositories. People reach for a second repository when what they actually want is a boundary, and a repository is a ruinously expensive way to draw a line you can draw for free in the filesystem.
-
There Is No Audience-Independent Architecture View
Every team eventually asks for "the architecture diagram", singular, the one picture which explains the system to everyone. That diagram cannot exist, because usefulness and audience-independence trade off by construction. The standards knew this in 1995. The answer is one model, many audience-specific views, and a clear separation between structural views and cross-cutting perspectives.
Read more on my blog: There Is No Audience-Independent Architecture View
-
In the last post I argued against quality assurance as a separate activity. The same argument applies, almost word for word, to code reviews, and I am even less comfortable making it: at Qafoo we built a code review tool. On an internal product team the asynchronous pull-request review has become the default, and it is the wrong tool for almost everything we use it for.
-
I co-founded a consultancy that sold software quality for roughly a decade. The advice I am most certain about after those years sounds like a contradiction coming from me: do not do quality assurance as a separate activity. The moment a dedicated QA role appears, the developers quietly stop owning the quality of their own work, and that is the wrong direction.
-
HTMX and Web Components Instead of React
Our data platform's frontends are catalogs, dashboards, and detail pages: request/response-shaped applications. We build them with server-side rendering, HTMX, and vanilla web components. The question is not "why not React", but which of our actual problems a client-side framework would solve. Walking through the inventory the answer was: none, at a price we would pay for a decade. As a bonus, making components an explicit opt-in turns accessibility from discipline into the default.
Read more on my blog: HTMX and Web Components Instead of React
-
Style the Document, Not a Component Tree
BEM and CSS Modules solve scoping at the cost of making every element a one-off, and a pile of isolated components is not a design language. We style semantic HTML elements directly, constrain every color and distance to CSS variables, and use a small web-component base class instead of a framework. These old-fashioned rules matter more than ever now that LLMs generate frontend code faster than any human team could.
Read more on my blog: Style the Document, Not a Component Tree
-
Nothing Shared, Everything Gained: What It Cost to Finish
I left the start-up world not because I failed, but because I'd optimized for the wrong metric — I was building systems that scaled while being the system that wasn't. This is the post I wasn't sure I'd write, about why "Nothing Shared, Everything Gained" needed me to stop before it could be finished.
Read more on my blog: Nothing Shared, Everything Gained: What It Cost to Finish
-
Nothing Shared, Everything Gained: Boring Scales
Every few years our industry discovers a new way to make software development complicated, but most web applications are not technically interesting — the interesting part is the domain. My book is deliberately boring: four layers, strict dependency direction, stateless services, and it worked the same way for five engineers and for seventy.
Read more on my blog: Nothing Shared, Everything Gained: Boring Scales
-
Nothing Shared, Everything Gained: The Architecture
The entire architecture in the book fits into one sentence: Controller → Service → Gateway → Storage, with strict dependency direction and one job per layer. It isn't a new methodology, it's a distillation of practical experience into four concepts that, put into perspective, prevent most structural problems from ever appearing.
Read more on my blog: Nothing Shared, Everything Gained: The Architecture
-
Nothing Shared, Everything Gained: The Thesis
Writing testable code is essential, but writing tests is not — at least not immediately, because comprehensive suites for code that might get cut next sprint are waste, not discipline. The actual non-negotiable is pushing side effects to the edges so that the code between them stays stateless, local, and changeable without fear.
Read more on my blog: Nothing Shared, Everything Gained: The Thesis
-
Nothing Shared, Everything Gained: The Problem
A team that hadn't shipped anything in six months, controllers with NPath complexity causing integer overflows, 2000-line methods, and session arrays nobody understood — and twenty-five days later they were shipping again. The same pattern repeated across more than a hundred teams over seven years, and the common thread was always side effects.
Read more on my blog: Nothing Shared, Everything Gained: The Problem
-
Nothing Shared, Everything Gained: The Origin Story
Ten years ago I started writing a book about software architecture and then life happened: I co-founded a company, scaled it to seventy engineers, got acquired, and burned out. The decade in between didn't make the book obsolete, it proved the ideas worked, and the finished result is now available at codethatships.com.
Read more on my blog: Nothing Shared, Everything Gained: The Origin Story
-
Fast Fashion for Code: How the Power Grab Masks a Quality Crisis
AI code generation isn't the industrialization of software development that vendors promise. It's fast fashion: cheap, disposable, and hiding a massive structural shift in power from the people who build software to the companies that control the means of generating it.
Read more on my blog: Fast Fashion for Code: How the Power Grab Masks a Quality Crisis
-
From Commerce to Campus: A New Stack, A New Purpose
After fifteen years of founding companies and scaling commerce platforms, I'm now a software architect at FernUni Hagen, building a Learning Analytics data platform that helps students succeed, with a Modern Data Stack and consent-first design for highly sensitive data. I made the switch for meaning and work-life balance, and found both, plus an amazing team to work with.
Read more on my blog: From Commerce to Campus: A New Stack, A New Purpose
-
Women in IT: The Structural Problem Nobody Wants to Fix
I've conducted over 1,000 interviews and hired around 70 developers. My experience is clear: women with comparable qualifications consistently deliver better work, not because they're inherently better, but because the system forced them to be. Meanwhile, most companies' DEI efforts are pinkwashing, hiring still runs through bro networks…
Read more on my blog: Women in IT: The Structural Problem Nobody Wants to Fix
-
Why I Built Hejme, Part 3: Families Define Themselves
I'm in a boring traditional marriage, but I built Hejme for complex families: divorced, blended, geographically scattered. Why? Because everyone I talked to had the same need: share with exactly the right people, not some platform's template. You decide who's family. The software should just make it easy.
Read more on my blog: Why I Built Hejme, Part 3: Families Define Themselves
-
Why I Built Hejme, Part 2: What I Know About Your Data
After 20 years in tech, I've seen how the business model works: free products need another revenue source, and that source is you. Your attention, your data, your family photos as engagement bait. So I'm building something with aligned incentives. You pay, I work for you. No ads, no tracking.
Read more on my blog: Why I Built Hejme, Part 2: What I Know About Your Data
-
Why I Built Hejme, Part 1: The Photos You've Never Seen
I share photos of my daughter daily, just not publicly. She can't consent to existing on the internet yet. Then I missed my brother's vacation because Facebook decided crypto drama was more important. That's when I realized: our tools treat sharing and publishing as the same thing. They're not.
Read more on my blog: Why I Built Hejme, Part 1: The Photos You've Never Seen
-
The LLM Trap: Why We're Trading Our Future for Convenience
After weeks of building with LLMs, I need to acknowledge an uncomfortable truth: this approach is fundamentally unsustainable, and I should have hired junior developers instead.
Read more on my blog: The LLM Trap: Why We're Trading Our Future for Convenience
-
The LLM Reality Check: Why AI Can't Replace Strategic Software Development
Building an MVP with LLMs over the past few weeks has revealed two fundamental limitations that define exactly how AI fits into software development workflows: non-trivial tasks fail about 40% of the time regardless of prompting quality, and code quality correlates directly with how often other developers have solved the same problem online.
Read more on my blog: The LLM Reality Check: Why AI Can't Replace Strategic Software Development
-
The Blessing of Opinion-Free Development
After twenty years of managing development teams, I've discovered something liberating about coding with LLMs: they don't have opinions about technical architecture.
Read more on my blog: The Blessing of Opinion-Free Development
-
LLMs: Overeager Junior Developers on Cocaine
I've been building an MVP for a stealth startup over the past few weeks, coding extensively with LLMs. After managing development teams for years, I can finally articulate what working with Claude, Cursor, and friends actually feels like: like supervising an overeager junior developer on cocaine.
Read more on my blog: LLMs: Overeager Junior Developers on Cocaine
-
The Irony Of Building A Perfect Desk While Not Working
So here's the thing: After stepping away from tech leadership to take a year off, what's the first thing I do? Spend weeks meticulously crafting the perfect desk setup. Because apparently, the best time to build your dream workspace is when you're not actually working. 🤔
Source: The Irony Of Building A Perfect Desk While Not Working
-
My Local Development Environment on NixOS
Probably irrelevant to most, but still logging this. How do I set up my
local development environment while using NixOS? For different projects I
require different tools, which I do not always have installled globally. In
the past I was using the nix-shell command manually but now I automated
it…
-
After an incredible journey, I've closed my chapter at commercetools. What
started as a startup dream with Frontastic evolved through funding,
acquisition, and growth into something larger than we could have imagined.
Now, it's time for something new – though I'm not yet sure what that "new"
will be…
-
Remote First: Never meet in person?
Does remote-first or remote-native mean that you'll never meet your peers
in person? I certainly diagree. But you'll meet intentionally and usually
this'll mean intense and productive collaboration.
-
Product development is not Open Source development
The most visible software development is the Open Source community and many
developers (including myself) have learned work and software patterns
there. I'm convinced though that those patterns differ significantly from
developing a SaaS product and that you should pay attention to these
differences. My key take away is: Be careful when changing the surface,
but stay flexible on the inside.
-
Understand your ideal customer profile
In my previous companies I've never even heard about the ideal customer
profile (ICP) but this helpd me (and also other members of the founder and
product teams) a lot when priotizing and making decisions in general. What
is this and how does it affect the technology stack?
-
Delegation is hard, but this might help you
How do you learn to delegate and learn what to delegate when? And when are
you still allowed to do something by yourself and, for a moment, delay
transfering knowledge to your teams? How to make sure all relevant
knowledge about the stack is transferred to right people, so that your
teams are able to take responsibility for those components in the future.
-
Software architecture and product market fit
Which software architectural principles are important when funding a SaaS
product company and how to adapt it to the change you'll see in your
product?
-
Focus time for developers and everybody else
Everybody knows that focus time is important especially for individual
contributor levels. But also in a management role I value focus time a lot
for strategic work, research, analysis, and sometimes even just to be able
to process all input and reflect on what the current state and bigger
picture are. How to achieve this and combine this with nobody being blocked
because of missing information in remote environments?
-
While we are beyond the peak of the hype curve an often asked question
still is about when to create microservices. Let me share what I use as a
decision base.
-
Frontastic Becomes Part of commercetools
Frontastic becomes part of commercetools – I am really happy to be part of
this journey and continue as the CTO Composable Frontend Platform in our
joint venture.
-
How to Refactor Your Legacy Code: A Decision Matrix
When you are beginning to consider refactoring your big legacy codebase
towards a new software design, then it is not uncommon to feel helpless
after estimating this to be a huge terrifying 2-5 years project. To help
solve the problem of not knowing where and how to begin, we have had great
success using a decision matrix to decide how each part of the legacy code
should be changed in such a refactoring project. Two main factors should
influence your refactoring decisions…
-
Many projects I join - even those that claim to already do dependency
injection - suffer from issues that result from mixing injectable and
newable classes. Keeping these two appart seems to be challenging for
many developers so that I try to give them a handy guide with Do's and
Dont's in this blog post.
-
Checklist For A Reliable Load-Test
Setting up a load-test that produces results you can rely on is not that
simple. But without realistic test-results you cannot be sure that your
application handles sudden increases of traffic, rapid spikes or even the
initial go-live. And you cannot estimate at which number of users you
should scale up your hardware. Both details are very important to keep the
application running at all times and guarantee that no revenue or developer
sleep is lost because of outages. We have a large checklist of points we go
through when setting up performance tests with customers and I wanted to
discuss some of the more important points in this blog post.
-
Why Apache Benchmark Is Not Enough
You are working for months on a new web application or e-commerce system
and usually a few weeks or just days before the launch a complete enough
feature set is running on a production-like system so that you can run a
realistic load-test. Hopefully providing you with accurate picture of the
performance of your future system. What should you do, and why is Apache
Benchmark usually not sufficient?
-
Refactoring Singleton Usage to get Testable Code
So your code base is littered with singletons and using them? Don't worry,
you can start refactoring them out of your code base class by class and
introduce increased testability at every step. This strategy is very simple
to implement and the propability of breaking your code is very low,
especially when you are becoming more experienced with this technique.
-
Five Tips to Improve Your Unit Testing
After you got the hang of unit testing there is still so much space for
improvement. In this post I want to share five tips with advanced testers I
have seen to influence testing in the right direction.
-
Refactoring with the Advanced Boy Scout Rule
When we join teams to coach them with refactoring their legacy code base,
many of them are overwhelmed by the sheer mass of code. That typically
results in the request for "some refactoring sprints" or even "a complete
rewrite". Both is obviously not a solution from the business perspective -
feature development and bug fixing needs to go on and the refactoring
should not eat up the larges portion of time. But where and how should the
team start and how should? What we call the "Advanced Boy Scout Rule" has
helped many teams to come over this staleness and reach fast results while
continuing to deliver business value.
-
Software systems usually get more complex over time. In the beginning a
variable starts out to represent something very simple with very few rules
and constraints that can are enforced in a single location of the code. We
will show you how you can use value object extraction to avoid spreading
logic everywhere.
-
A long time ago I wrote a blog post about Testing file uploads with PHP
where I have used a CGI PHP binary and the PHP Testing Framework (short
PHPT), which is still used to test PHP itself and PHP extensions. Since
the whole topic appears to be still up-to-date, I would like to show a
different approach how to test a fileupload in PHP in this post. This time
we will use PHP's namespaces instead of a special PHP version to test code
that utilizes internal functions.
-
How You Can Successfully Ship New Code in a Legacy Codebase
Usually the problems software needs to solve get more complex over time. As
the software itself needs to model this increased complexity it is often
necessary to replace entire subsystems with more efficient or flexible
solutions. Instead of starting from scratch whenever this happens
(often!), a better solution is to refactor the existing code and therefore
reducing the risk of losing existing business rules and knowledge. A good
strategy for this kind of change is called "Branch By Abstraction". While
the term is certainly clumsy and overloaded, the idea itself is genious.
Let's see how it works…Source: How You Can Successfully Ship New Code in a Legacy Codebase
-
Many developers want to "rewrite the whole application" and "get rid of all
that sh*t". Most of them are pretty blank when I tell them that I really
like working on such code bases, even if I just jumped into the code. I
recently talked about that to the other Qafoo members and all of them
agreed to my views. Therefore I want to explain our love of legacy code in
this post.