I’ve been writing code since I was about eight years old. Over that time the tabs vs spaces debate has come up more times than I can count.
I started with BASIC on a Sinclair ZX81. Then, I moved on to an Acorn Electron. I later looked on with envy at a neighbour. This neighbour was a few years older than me. They had all the exciting kit — Atari machines and then an Amiga. I eventually bought an Amiga A500 Plus with my first pay cheque, later an A1200, and that’s where I first started experimenting seriously with C and C++.
After a break, I returned to university in the late 1990s to formally study Computer Science.
I’m now fifty, and while I still care deeply about code quality, I’ve learned that some of the “religious wars” of our industry are better approached with perspective than pitchforks. The tabs vs spaces debate is a perfect example.
This isn’t a rant. It’s a preference — informed by a lot of years reading, writing, reviewing, and maintaining other people’s code.
What a tab actually is (and isn’t)
A tab character does not represent a fixed amount of whitespace.
A tab is an alignment character. When rendered, it moves the cursor to the next tab stop. Where that tab stop lies depends entirely on editor configuration. One developer might use tab stops of 2 spaces, another 4, another 8 — all perfectly valid choices.
This flexibility is intentional, and it’s also where most problems start.
Legitimate reasons to use tabs
There are good, well-established reasons to use tabs, and it’s worth stating that clearly:
- Accessibility: Tabs allow developers to adjust indentation width to suit eyesight or personal preference without changing the file.
- Established conventions: Some ecosystems explicitly require tabs (Makefiles being the canonical example).
- Column alignment: Tabs can be genuinely useful for aligning tabular data.
- Long-lived codebases: Many large projects standardised on tabs decades ago, and consistency matters more than re-litigating old decisions.
Using tabs in these contexts is not wrong, careless, or outdated.
In collaborative environments, tabs can introduce subtle problems when:
- Contributors use different tab stop widths
- Indentation is done manually rather than via editor automation
- Tabs are used inconsistently or mixed with spaces
The result is familiar: code that looks neatly structured in one editor becomes misaligned and hard to read in another. This isn’t because tabs are “bad” — it’s because their visual meaning is contextual.
When indentation carries semantic or cognitive weight — as it does in Python, YAML, or deeply nested logic — that variability becomes a real source of distraction and, occasionally, error.
Why I still prefer spaces
Personally, I prefer spaces for indentation.
Not because tabs are invalid, but because spaces optimise for predictability:
- A space is always exactly one column wide.
- What you see in your editor is what everyone else sees.
- Structure and alignment are unambiguous.
- Diffs are cleaner and easier to review.
- Accidental misalignment is harder to introduce.
In practice, spaces achieve the same aim as tabs — expressing structure — but with fewer moving parts. After a few decades of working on large, shared codebases, I’ve come to value that reduction in ambiguity more than the flexibility tabs provide.
This is why I enable “insert spaces instead of tabs” in every editor I use. Not out of dogma, but because it removes an entire category of avoidable problems.
tabs vs spaces: The real problem isn’t tabs — it’s inconsistency
If there is a genuine villain in this debate, it’s inconsistency.
Mixing tabs and spaces without a clearly enforced standard is a reliable way to:
- Break visual structure
- Generate noisy diffs
- Turn code reviews into archaeology
Fortunately, this is much easier to manage today than it was when this debate first flared up.
tabs vs spaces in Code: A brief note on modern tooling
In 2026, this debate is far less painful thanks to tooling:
- EditorConfig allows projects to declare indentation rules once and have them respected across editors.
- Auto-formatters (Prettier, Black, gofmt, clang-format, rustfmt) remove human inconsistency entirely.
- Linters and CI checks can enforce formatting automatically and objectively.
- IDE defaults are far better than they used to be, and much easier to standardise.
With the right tools in place, teams can safely use tabs or spaces and still achieve clean, readable, consistent code.
Closing thoughts
Tabs vs spaces isn’t a moral issue, and it isn’t a measure of engineering quality. It’s a trade-off between flexibility and determinism.
I choose spaces because they give me the same outcome with fewer surprises. Others choose tabs for equally valid reasons. What matters far more than the choice itself is that teams agree, document it, and let tooling enforce it.
After fifty years on this planet — and many of them writing code — I’ve learned that consistency beats ideology every time.
Footnote:
This piece is a rewrite of a much more forcefully worded post I originally wrote in 2009. At the time, the tabs vs spaces debate felt like a hill worth dying on. With a few more decades of experience — and a lot more shared codebases behind me — I’ve come to value consistency, tooling, and pragmatism far more than winning arguments. I still prefer spaces, for the reasons outlined above, but I’m much happier these days letting formatters and standards do the heavy lifting.
