Why I Think Naming Is a Load-Bearing Engineering Decision

Why I Think Naming Is a Load-Bearing Engineering Decision

In 2019 I inherited a fintech infrastructure spread across two data centers in Lagos and a backup node in Accra. The previous team had left behind no architecture diagrams, no runbooks, and a Confluence space untouched in fourteen months. What they did leave was hostnames: lag-db-01, lag-db-02, acc-db-01, lag-app-prod-03, lag-app-prod-04, and a single machine called the-old-thing that turned out to be running a critical reconciliation service nobody had documented.

Those hostnames were the only map I had. For the first three months, every incident response, every capacity decision, every deployment plan started with ssh into a machine based on its name, reading what was running there, and reconstructing the system from the ground up. The naming convention was not pretty. It was not consistent. the-old-thing was an active crime against clarity. But those names were load-bearing. They carried operational weight that the missing documentation could not.

This is why I think naming in engineering is not a cosmetic exercise. It is a documentation strategy that survives missing wikis, departed engineers, and 3 AM pages. When you work in environments where runbooks are aspirational and the team is three people across two time zones, the name on a hostname, service label, alert title, or postmortem document is often the only context an on-call engineer has. Treat it accordingly.

The Scenario: A Name That Almost Cost Us a Database

Six months into running that same infrastructure, we had a disk failure on lag-db-02. The on-call engineer, a contractor who had been with us for two weeks, saw the alert, logged into the machine, and began reading PostgreSQL logs to assess the damage. What he did not know was that lag-db-02 was not a replica of lag-db-01. It was the primary for the transaction ledger. lag-db-01 had been repurposed six months earlier as a read replica for reporting workloads. The numbering convention implied a hierarchy that no longer existed.

He almost initiated a failover to lag-db-01, which would have promoted a stale read replica with a twelve-hour lag to primary status. I caught it because I happened to be awake and saw the Slack message at 2:47 AM. But the near-miss was not his fault. He followed the implication of the name. The name lied.

This is the core problem. Names accumulate meaning over time, and unless you treat naming as an engineering practice with a maintenance lifecycle, the names will drift from reality until they become actively dangerous.

What a Hostname Must Carry When Documentation Does Not Exist

In well-funded environments, a hostname is a label. You look it up in a service catalog, cross-reference it with a CMDB, check the team ownership field in a service registry. In the environments I work in, a hostname is often the entire documentation surface. It has to encode role, location, environment, and ideally something about criticality, all in a string short enough to type without typos at 3 AM.

The convention I have converged on after years of operating in West African and South Asian infrastructure is a five-field structure: [region]-[role]-[env]-[seq]-[tag]. For example: lag-ledger-pri-01 tells you the machine is in Lagos, running the ledger service, in the primary environment, first in sequence. The tag field is optional but useful for annotating special hardware or known quirks: lag-ledger-pri-01-ssd or acc-ledger-rep-01-solar for a node running on solar power backup in Accra.

This is not original thinking. It is the same logic that drives asset identification in formal frameworks. The NIST Cybersecurity Framework treats consistent identification and enumeration of infrastructure components as foundational to managing cybersecurity risk. Their configuration checklists and asset identifier mappings exist because the name of a component is not just a label. It is the entry point for every downstream practice, from configuration management to incident response. In environments where you cannot afford a dedicated CMDB or a full-time documentation owner, a disciplined naming convention partially substitutes for that missing infrastructure. It is the cheapest documentation you will ever produce.

But I want to be specific about the trade-offs. The five-field convention works when you have fewer than 200 machines. Beyond that, sequence numbers start colliding, tags multiply, and you need a registry anyway. I have seen teams try to encode everything, owner, cost center, hardware model, into hostnames and end up with strings like lag-ledger-pri-01-ssd-dell-r740-felixops-cc-2341. That is not a hostname. It is a compressed database record. The line between useful naming and hostname-as-database is where this approach breaks down. Know your scale before you commit.

Service Naming for Monoliths That Might Never Be Decomposed

The cloud-native literature assumes you are building services. Named services. With clear boundaries. In reality, most teams I work with are running monoliths that will never be decomposed. Not because the team lacks ambition, but because the business cannot afford the engineering time to split them, and the traffic does not justify the operational complexity of distributed services.

When you name a monolith, you are naming something that will accumulate responsibilities for years. The name you choose will either help people understand what it does or actively mislead them. I have seen a service called api-gateway that, over four years, absorbed payment processing, notification dispatch, file upload handling, and a scheduled job runner. The name became a lie that made onboarding harder, because every new engineer assumed “API gateway” meant routing and authentication. It actually meant “the thing that does everything.”

My rule for monolith naming: name the function, not the architecture. If it processes payments and dispatches notifications, do not call it api-gateway or core-service. Call it payment-and-notify or ledger-worker. The name should describe what a new engineer would find if they opened the codebase cold. If the name requires a three-paragraph explanation in a wiki that does not exist, the name has failed.

For internal service-to-service communication, I prefer explicit role-based names over abstract ones. ledger-write and ledger-read are better than ledger-service when they are actually separate processes, even if they share a database. The name tells the caller what to expect. ledger-write implies mutations. ledger-read implies queries. If you later split them into separate deployments, the names already describe the boundary. If you never split them, the names still tell you what each entry point does.

Alert Names Are Runbook Titles

If hostnames are the first layer of naming-as-documentation, alert names are the second. And they are where I see the most damage from careless naming.

An alert titled High CPU on lag-app-prod-03 tells you nothing useful at 3 AM. Is this critical? Is there a runbook? Does anyone care if CPU is high on this machine? An alert titled Ledger Primary Disk Usage Above 85% — Page Felix tells you exactly three things: which service, which severity implication, and who to call. The alert name is a compressed runbook.

The Google SRE book dedicates entire chapters to practical alerting, being on-call, and effective troubleshooting because alerting is not a monitoring problem. It is a communication problem. The Google SRE book’s table of contents shows how seriously this discipline is treated: monitoring, alerting, on-call, troubleshooting, incident response, and postmortem culture are each given their own chapter. What ties them together is that every one of these practices depends on unambiguous naming of the components being monitored, the alerts being fired, and the incidents being tracked. Google treats these as named, structured disciplines. Most teams treat them as ad-hoc activities, and the naming reflects that.

The alert naming convention I enforce is: [Service] [Specific Condition] [Expected Action]. Examples:

  • Ledger Primary Disk Above 85% — Clear WAL Archive
  • Payment Gateway Timeout Rate Above 5% — Check PSP Status
  • Accra Replica Lag Above 60s — Do Not Failover

That last one is specific and learned from experience. During a network degradation between Lagos and Accra, the replica lag alert fired, and the on-call engineer initiated a failover because the alert did not say not to. The alert name now carries that instruction. It is not elegant. But it prevents a repeat of the same mistake.

The trade-off: these names are long. They take up screen real estate on phone notifications. They look ugly in dashboards. But they work. They compress the most important information, what is wrong and what to do, into the one field that an engineer will definitely read. I will take ugly and functional over elegant and ambiguous every time.

Inherited Names and Vendor Defaults

The hardest naming problem is not choosing new names. It is dealing with names you inherited from vendors, cloud defaults, or previous teams. These names carry assumptions that are usually wrong for your environment.

Cloud providers default to names like ip-10-0-12-34.ec2.internal or instance-20231104-fg2h. These names tell you nothing about role, environment, or criticality. They are unique identifiers, not operational labels. If you are running on a cloud provider, tag your instances with the same five-field convention and make sure your monitoring and alerting systems use the tags, not the cloud-assigned hostnames. In AWS, this means your CloudWatch alerts should reference the Name tag, not the instance-id. In environments where you are running on bare metal or VPS providers without tagging, set the hostname explicitly on first boot and never rely on the provider default.

Vendor defaults are worse when they leak into service names. I inherited a service called rabbit-queue-processor that was actually processing payment webhooks. The original engineer named it after the technology, RabbitMQ, rather than the function, payment webhook processing. When we migrated from RabbitMQ to a PostgreSQL-based queue, the name became a lie. We renamed it webhook-receiver during the migration, but for six months, documentation and monitoring dashboards referenced a RabbitMQ service that no longer existed.

My rule: never name a service after the technology it uses. Technologies change. Functions do not. webhook-receiver survives a queue migration. rabbit-queue-processor does not.

Postmortem Titles and Document Names

The naming discipline extends beyond infrastructure into the editorial side of engineering work. Postmortem titles, runbook names, and internal document titles follow the same principle: the title is the first piece of documentation, and it should carry enough context to be useful without being opened.

I have seen postmortems titled Incident 2024-03-15. That title tells you nothing. A postmortem titled 2024-03-15 Ledger Primary Disk Full — WAL Archive Failure Caused 4-Hour Write Outage tells you the date, the service, the root cause, and the impact, all in one line. When you are searching for precedent during a similar incident, the second title is findable. The first one is not.

Runbooks follow the same logic. Database Failover Procedure is vague. Failing Over Ledger Primary from Lagos to Accra Replica is specific. The second title tells you exactly what the document covers and, just as importantly, what it does not cover. If you need to fail over the notification service, you know this is the wrong document before you open it.

For engineers who get stuck on naming internal documents, postmortem reports, or engineering wiki pages, reaching for a practical book title generator can help break the blank-page paralysis that hits when you are staring at a title field at the end of a twelve-hour incident. You are not writing a novel, but the editorial discipline of choosing a title that communicates scope and content is the same whether the document is a postmortem or a chapter in a technical book. The title is the first thing a reader sees, and in engineering documentation, it is often the only thing a stressed engineer reads before deciding whether to open the document at all.

The Hidden Cost of Renaming

Renaming is expensive. Every rename touches monitoring configurations, alert rules, runbook references, deployment scripts, DNS records, and the institutional memory of every engineer who has ever interacted with the system. I once renamed a service from queue-worker to transaction-processor and spent the next three weeks finding references in places I did not know existed: a cron job that monitored the old name, a Grafana dashboard buried in a folder nobody checked, a shell script on a bastion host that hard-coded the service name into a health check.

The cost of renaming is proportional to how long the old name has existed and how many systems have silently accumulated dependencies on it. This is why getting the name right early matters. Every month you delay a rename, the cost increases. But every rename you do without a plan creates a period where old names and new names coexist, and that period is when mistakes happen.

My approach to renaming: do it during a deployment that already requires coordination, not as a standalone change. If you are migrating a service to a new machine, rename during that migration. If you are upgrading PostgreSQL major versions, rename the service during the maintenance window. Bundle the rename with a change that already has an outage window, a runbook, and human attention. Never rename as a quiet background task, because the breakage will surface at the worst possible time.

Checklist: Naming as Engineering Practice

Before I close, here is the checklist I use when evaluating whether a naming convention is load-bearing or cosmetic:

  1. Can a new engineer infer the role from the name alone? If they need a wiki page to understand what the name means, the name has failed as documentation.
  2. Does the name describe function, not technology? webhook-receiver survives a queue migration. rabbit-processor does not.
  3. Does the alert name include the expected action? If an alert fires and the on-call engineer has to search for a runbook, the alert name is incomplete.
  4. Is the name stable across infrastructure changes? If moving a service from one machine to another changes the name, your naming convention is tied to hardware, not function. Fix that.
  5. Does the postmortem title contain date, service, root cause, and impact? If not, it will not be findable when someone searches for precedent during the next incident.
  6. Have you checked for hidden references before renaming? Search dashboards, cron jobs, shell scripts, and any file that might hard-code the old name. There are always more references than you think.
  7. Is the name typeable without typos at 3 AM? If it requires copy-paste or has ambiguous characters (0 vs O, 1 vs l), it will cause operational errors under stress.
  8. Does the name scale beyond 10 machines without collision? If your convention works for 5 machines but breaks at 50, you will outgrow it before you have time to replace it.

Conclusion

Naming is the cheapest documentation you will ever produce and the most expensive to get wrong. In environments where runbooks are aspirational, team memory is short, and the person on call might have been with the company for two weeks, the name on a machine or an alert is the difference between a five-minute fix and a four-hour outage. The cloud-native world can afford to treat naming as an aesthetic concern because it has service registries, CMDBs, and dedicated SRE teams to compensate for bad names. Most of the world does not have that luxury.

Treat naming like you treat configuration: version it, review it, and when it drifts from reality, fix it before it lies to someone who is depending on it.