Abstract shapes falling into preset positions — some aligned, some misaligned — representing the invisible force of default configurations

Every codebase has two kinds of decisions: the ones someone made on purpose, and the ones nobody made at all.

The second kind runs the world.

A default is what happens when nobody specifies otherwise. The initial value. The unchecked box. The behavior you get on a fresh install with a blank config file. Defaults are invisible — they don't show up in pull requests, they don't get debated in architecture meetings, and they don't appear in changelogs. They just are.

That's what makes them so powerful. Most users never change the defaults. Most developers never question them. The default becomes the behavior, the behavior becomes the expectation, and the expectation becomes permanent. By the time someone notices the default was wrong, it's too late to fix it.

Here are five defaults that shaped computing. None of them were malicious. All of them were consequential.

MySQL's "UTF-8" isn't UTF-8

In 2002, MySQL added support for a character encoding called utf8. Reasonable name. You'd assume it implements UTF-8 — the universal character encoding that handles every language, every symbol, every emoji.

It doesn't.

MySQL's utf8 only uses three bytes per character. Real UTF-8 uses up to four. Three bytes covers 65,536 characters — enough for most Latin, Cyrillic, Arabic, and CJK text. Not enough for emoji, mathematical symbols, musical notation, or several rare scripts.

For years, this didn't matter. Then emoji happened. Suddenly every application that stored user input needed four-byte characters, and every MySQL database with the default utf8 encoding silently corrupted or rejected them. The fix? A separate encoding called utf8mb4 — which is just... actual UTF-8.

MySQL couldn't rename the original utf8 to what it really was without breaking every existing database that referenced it. So now there are two "UTF-8" options, one of which is a lie, and the real one has a name that implies it's some exotic variant rather than the standard. utf8 was deprecated in MySQL 8.0. It took eighteen years.

The default encoding that millions of databases were created with was silently incomplete, and the name was silently misleading. Nobody chose this. It just happened.

CSS makes every box the wrong size

When you set width: 200px on an HTML element, you would reasonably expect it to be 200 pixels wide. With CSS's default box-sizing: content-box, it isn't — padding and border get added to the width. A 200px box with 20px of padding and a 1px border is actually 242 pixels wide.

This is how CSS has worked since 1996. It makes mathematical sense if you think about it in terms of the content area. It makes no intuitive sense to anyone trying to build a layout.

Internet Explorer 6, ironically, got it "right" in quirks mode — its box model included padding and border inside the specified width. The standards said IE was wrong. Developers agreed with IE.

The result: virtually every CSS reset stylesheet in existence includes box-sizing: border-box applied to every element. It's so universal that it has its own shorthand — "the box-sizing reset." Entire CSS frameworks exist partly to paper over this default. An entire category of layout bugs exists exclusively because of it.

Nobody ever chose content-box. It was just the default. And thirty years later, every web developer's first act is to undo it.

Python shares your list with everyone

def add_item(item, items=[]):
    items.append(item)
    return items

What does add_item("a") return the third time you call it? If you said ["a"], you're wrong. It returns ["a", "a", "a"].

Python evaluates default arguments once, when the function is defined — not when it's called. That empty list [] is created a single time and shared across every call. Append to it, and you're appending to the same object every caller sees.

This is Python's most famous gotcha. It's in every "common mistakes" article. Every linter flags it. Every tutorial warns about it. It has been a known source of bugs since the 1990s. And it still trips people up, because the syntax looks like it creates a new list each time.

The fix is a two-line pattern: use None as the default, create the list inside the function body. Simple once you know it. Invisible until you don't.

def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

The language designers had reasons for this behavior — it's consistent with how Python objects work, and it enables some intentional patterns like memoization caches. But "consistent with the object model" and "what a human expects when they read items=[]" are different things. The default chose consistency over intuition, and decades of bugs followed.

HTTP cookies ship with no protection

When cookies were introduced in 1997, they had no security attributes. No Secure flag (send only over HTTPS). No HttpOnly flag (hide from JavaScript). No SameSite attribute (restrict cross-origin sending). A cookie was a cookie — it went everywhere, and anything could read it.

This default — cookies with no protection unless you explicitly add it — created the attack surface for two of the most common web vulnerabilities in history:

Cross-site scripting (XSS): Injected JavaScript reads the user's session cookie via document.cookie. If the cookie had HttpOnly, the script couldn't access it. But that flag wasn't added until 2002, and it's still not the default — you have to opt in.

Cross-site request forgery (CSRF): A malicious page submits a form to your bank, and your browser helpfully sends your authentication cookie along with it. SameSite addresses this, but it only became a standard in 2016, and browsers only defaulted to SameSite=Lax in 2020.

For twenty-three years, every cookie was born vulnerable. Every developer who forgot to add the right flags — and most did, because the defaults felt fine — left their users exposed. The security didn't fail. It was never turned on.

The lesson

These aren't obscure edge cases. They're MySQL, CSS, Python, and HTTP — foundational technologies that billions of systems run on. In each case, the default was set by smart people making reasonable tradeoffs with the information they had. And in each case, the default turned out to be wrong in ways that became apparent only after widespread adoption made it unfixable.

The pattern is the same every time:

  1. A default is chosen (or not chosen — which is itself a choice)
  2. The default works well enough that nobody questions it
  3. Scale reveals the problem
  4. By the time the problem is obvious, changing the default would break everything
  5. The workaround becomes permanent

If you're designing software, your defaults deserve more thought than your features. A feature is something a user chooses. A default is something a user gets. The feature serves the people who find it. The default serves everyone who doesn't.

Make the safe thing the default. Make the intuitive thing the default. Make the thing that most people would choose if they understood the options — the default.

The code nobody writes runs the world. Write it carefully.