Sebastiano Druda

← Back to writing

Field note / Software Engineering

The Best Code Is Often the Code You Can Delete

Removing a visitor counter simplified an entire operating model. A field note on maintenance cost, safe deletion and responsibilities hidden behind features.

The visitor counter on this website occupied very little space. Its maintenance footprint was considerably larger. Keeping a number in the footer meant preparing a Node service, persistent SQLite state, service management and a reverse proxy, alongside the static publication itself.

None of those technologies was inherently inappropriate. Together, they answered a requirement that had become difficult to justify. The site needed to present work, publish articles and help readers find them. Counting visits was peripheral to those tasks, yet it was shaping the production architecture.

Removing the counter changed the operating model more than polishing its implementation could have done. This is the part of maintainability I want to examine: what disappears from future work when a requirement disappears from the product?

A feature continues after its code is written

The initial implementation cost is easy to see. Someone adds a component, writes a handler and checks that the expected value appears. The subsequent obligations are spread across time and are therefore easier to underestimate.

A persistent service needs a startup procedure. Its runtime needs updates. Its state needs a recovery policy. A future deployment must distinguish generated files from live data. Documentation has to explain how those parts fit together. Even if nothing breaks, someone must remember that these responsibilities exist.

Every feature has a maintenance shadow. Some shadows are entirely justified. An account system may be central to a product. A payment ledger cannot be removed because backups are inconvenient. The question is whether the ongoing responsibilities are proportionate to the value being delivered.

For this website, the visitor counter was a useful place to ask that question because the rest of the product could be expressed as static output. Removing it did not leave another hidden requirement for the same runtime. The simplification could reach the whole delivery path.

Count concepts before counting lines

A line-count reduction can be misleading. Replacing explicit code with an obscure abstraction may shorten a file while making the system harder to understand. Similarly, moving a service to an external provider may remove local code without removing the dependency or its operating consequences.

The useful inventory for this change was conceptual:

Proposed operating modelCurrent operating model
Astro plus a visitor APIStatic Astro pages
Persistent visitor stateSource-controlled content
Node process and service managementBuild-time Node tooling
Reverse proxy and VPS preparationStatic shared-hosting target
Runtime metric collectionBrowser-only footer information

Pagefind supplies search from the built site, and GitHub Actions prepares the release. These still require maintenance, but they fit the existing build boundary. There is no production database introduced by publishing another article.

This comparison describes the repository’s architectural direction. It does not claim that the former VPS system had been running in production or causing incidents. Avoiding an unnecessary obligation before launch is a valid outcome; it does not need an invented outage to make the decision sound important.

Deletion needs a dependency trail

Removing the visible counter would have been an incomplete change. If the browser continued fetching its value, the runtime dependency would remain. If the deployment guide still instructed someone to start the service, the next maintainer might reasonably recreate it.

The cleanup followed the feature through its consumers and operating artifacts. The footer markup, request code, service entrypoint, storage implementation, dedicated tests and obsolete deployment instructions all had to agree that the feature was gone.

That trail also establishes what should stay. A repository rule that prevents accidental database files from being committed remains useful even after the application stops creating them. A release guard that rejects private state protects the static output. Deleting feature code does not imply deleting every safeguard that mentions the old kind of file.

I think of this as removing a supported path through the system. At the end, there should be one coherent current explanation. Historical documentation can record the old decision, but it should not compete with the active setup instructions.

Boring is an operating property

The Simplicity chapter in Google’s SRE book connects predictable systems with reliable operation and discusses unnecessary complexity as a cost. I take that as a useful lens, not as evidence that this small website needs the processes of a large infrastructure organization.

For the site, predictability means a maintainer can identify the source, run the documented checks, build the output and understand which files reach the host. A content edit should not require reasoning about a persistent visitor database or restarting an unrelated service.

There are still failure modes. Dependencies can stop installing. A build can fail. An upload can be interrupted. The provider can serve incorrect cache headers. The simpler design does not erase these possibilities; it makes the relevant operating questions more closely match the product.

A smaller maintenance surface is one you can explain and verify.

The goal is not to produce a diagram with the fewest boxes at any cost. Combining unrelated responsibilities into one opaque script would make the picture smaller while making recovery harder.

Preserve behavior at the boundary

Deletion deserves tests where it can affect the product. In this case, the remaining footer information needed to render correctly, navigation and search needed to work, and the generated release needed to contain only the static site.

A useful test asks whether a reader can still complete the important task. It does not require keeping implementation-specific tests for a component that no longer exists. Retaining those tests would make the repository insist on an intentionally removed requirement.

The distinction can be subtle. A test that the footer exposes approved contact information still matters. A test that a counter endpoint increments does not, once the product no longer includes a counter. A test that production makes no request to the removed API can temporarily provide useful regression protection.

The architecture discussion approaches the same issue from requirements and trade-offs. Here the trade-off was explicit: give up a peripheral metric in exchange for a smaller operating model, while preserving the publication’s useful behavior.

Reversibility is more valuable than dormant machinery

One reason teams hesitate to delete code is the possibility that the feature will return. That possibility is real. It does not automatically justify carrying an unused system indefinitely.

Source control preserves the earlier implementation for reference. A future requirement should still be evaluated against the current architecture, current dependencies and current privacy expectations. Restoring old code verbatim may be less appropriate than implementing a different measurement approach or deciding that the metric is unnecessary again.

Keeping inactive infrastructure “just in case” creates another supported-looking path. Someone must know whether it still works, whether it is secure and whether its instructions remain valid. That is an ongoing cost even if nobody consciously chooses to use it.

A better form of reversibility is a short record of the decision: what was removed, what value was lost, what complexity disappeared and which future requirement would justify reconsideration. That record helps the next decision without pretending the old system is still maintained.

Start the next maintenance review with a requirement

A code review normally asks whether the implementation is understandable, tested and appropriately structured. A maintenance review can ask an earlier question: does the behavior still need to exist in this form?

For a small project, I would start with features that introduce a new category of operating work. A background process, a writable store or a separate credentialed service deserves a clear connection to a user need. The review should include who benefits, what would happen if the feature disappeared and whether a simpler product decision would preserve the important value.

That discussion must remain concrete. “We should simplify everything” gives no stopping condition. “This footer metric is the only reason production needs persistent application state” creates a decision that can be inspected and tested.

Deleting a requirement can be more powerful than optimizing its implementation.

In this case, the result was a website better aligned with its purpose, not a claim that smaller systems always win. The useful code is the code that supports a justified responsibility. Everything else deserves permission to leave.

Sources

  1. Google SRE: Simplicity — checked 2026-10-11

Topics

44 / Essay

Architecture Decisions Have Expiration Dates

Architecture decisions depend on assumptions that change. Record context, review triggers and migration costs so yesterday’s sensible choice stays visible.

software architecture · 7 min