20 years of being a programmer: what the job was, what it became, and what I’d train for now
Owen MacAllister
September 23, 2026
I started writing code when the job still meant mostly that: you opened an editor, you wrote functions, you shipped a build. Twenty years later I still write code, but that is no longer what people pay me for — not really. They pay for judgment around the code: what not to build, which dependency is a trap, how to explain a delay without lying, and how to keep a team moving when the stack changes under our feet every eighteen months.
This is not a memoir of every framework I survived. It is a field report on what the programming job actually was, what it became, and what I would train for if I were starting again in 2026 with clear eyes.
What the job was
In the early years, the craft was local. A good programmer knew the language, the standard library, and enough of the operating system to debug without begging. You owned a feature end to end because the surface area was small enough to fit in one head. Source control was a skill you learned on the job. Deployments were scary and infrequent. “Full stack” was not a LinkedIn badge; it was the default for anyone on a small product team.
Interviews matched that world. You could fail an algorithm puzzle and still get hired if you had shipped something real. Or you could ace the puzzles and fail in week three because you had never read someone else’s code. Either way, the expectation was clear: produce working software with a small group of people who sat near you.
The tools were crude by today’s standards and somehow less noisy. Autocomplete was limited. Search meant Grep and memory. Stack Overflow was a revelation, then a habit, then a risk. You learned by reading mailing lists, books with dog-eared pages, and the one senior engineer who would sit with you after hours. Mentorship was uneven, but when it happened it was deep, because there were fewer layers of abstraction between “I don’t understand this” and “here is the machine.”
I do not romanticize that era. Builds broke for opaque reasons. Security was often an afterthought. Women and underrepresented engineers got fewer second chances. Open source was both gift and unpaid labor. Still, the job description and the day-to-day were aligned: write code, fix bugs, ship.

What the job became
Somewhere between continuous delivery, cloud platforms, and the explosion of SaaS, the title “programmer” started meaning “person who holds the system together with glue.” The code is still there. It is just surrounded by tickets, compliance checklists, observability dashboards, design reviews, incident channels, and a product manager who needs a date by Thursday.
Modern programmers spend large stretches of time not writing new logic. They read pull requests. They triage flaky tests. They argue about ownership of a shared library. They translate business constraints into technical ones and technical constraints into business ones. They sit in meetings that exist because the org chart grew faster than the communication patterns.
The stack got taller. Frontend alone can consume a career. Backend split into services, then platforms, then platform teams that build tools for other teams. Data work bloomed into its own profession. Security stopped being a quarterly audit and became a continuous gate. AI coding assistants arrived and did not replace programmers so much as compress the cheap parts of the job while raising the bar on the expensive parts: taste, review, and responsibility.
Hiring changed with the market. Boom years rewarded narrative and velocity. Lean years reward evidence that you can own an outcome without a small army. Bootcamps and career-switch programs flooded the junior pipeline, then the junior pipeline dried up when companies decided AI could draft the ticket work. Mid-level engineers got asked to act like seniors. Seniors got asked to act like managers without the title or the pay. Staff engineers discovered that “technical strategy” often means politics with a diagram.
None of this means coding stopped mattering. The opposite is true. When anyone can generate a plausible first draft, the difference between a dangerous system and a durable one is still someone who can read the draft and say no. The job became less about typing speed and more about selection: which path, which trade-off, which risk you are willing to carry into production.
The skills that quietly took over
If I list what actually moved my career after year five, it is an awkward mix.
- Reading systems, not just files. Understanding how a request travels, where state lives, and what fails when a dependency hiccups.
- Writing for humans. Design docs, incident notes, PR descriptions that tell the reviewer what to fear. Code that explains itself beats clever code that needs a tour guide.
- Estimation as honesty. Not padding. Not heroics. A range with assumptions, and the courage to revise when the assumptions die.
- Conflict without drama. Disagreeing about an API shape without turning it into a personality contest.
- Ownership of the boring path. Logging, migrations, feature flags, rollback plans. The work that never trends on social media and always shows up in postmortems.
Soft skills is the phrase people use, and it sells the wrong story. These are not charm skills. They are engineering skills applied to people and time. A programmer who cannot explain trade-offs will keep building the wrong thing beautifully.
I also learned that deep specialization and broad judgment are not enemies. You need a spine of real technical depth — languages, data models, concurrency, security basics — or your “product sense” is just vibes. Then you need enough range to see when the bottleneck is not the code at all.

What I would train for now
If I were starting in 2026, I would not try to memorize every framework. I would build a portable core and then practice judgment in public.
1. One language deeply, two ecosystems lightly
Pick a mainstream language and stay with it long enough to be dangerous: memory model or GC behavior, tooling, testing, packaging, how packages actually get compromised. Then learn enough of a second ecosystem to stop being provincial. The goal is not polyglot theater. It is the ability to recognize the same problems wearing different syntax.
2. Data and interfaces before frameworks
Learn SQL for real. Learn how HTTP APIs fail. Learn what an index is for, what a queue buys you, and what eventual consistency costs the product. Frameworks come and go; the shape of data and contracts is what remains when you rewrite.
3. Ship something that other people depend on
A toy that only you use teaches syntax. A small tool with users teaches support, versioning, and regret. Open source, a workplace internal tool, a paid micro-product — the vehicle matters less than the feedback loop. You need the experience of breaking someone’s workflow and fixing it without disappearing.
4. Learn to use AI without outsourcing your taste
Treat assistants as aggressive autocomplete with a confidence problem. Use them to draft, explore, and clear boilerplate. Do not let them own design decisions you cannot defend. The market will punish people who can only paste and hope. It will reward people who can audit generated code the way seniors used to audit juniors.
5. Practice the meta-work early
Write short design notes before you build. Review other people’s PRs like you mean it. Run a tiny incident drill on a personal project: backup, restore, rollback. Learn how to say “I don’t know yet” in a way that still moves the conversation. These habits feel optional until you are the person on call.
6. Build a career story that is not a stack list
Hiring managers skim for outcomes: systems stabilized, costs cut, features that survived contact with users, teams unblocked. Keep a private log of decisions and results. When you update a resume, translate tools into consequences. The stack is evidence. The story is the product.
What I would stop training for
I would stop collecting certifications that expire into marketing. I would stop chasing every new UI library as identity. I would stop treating leetcode as the entire craft — it is a filter in some companies, not a career. I would stop waiting for a perfect mentor; peer groups, readable codebases, and writing in public have replaced a lot of the old apprenticeship for people willing to do the work.
I would also stop believing that title progression is the only scoreboard. Plenty of excellent programmers plateau in title while deepening impact. Plenty of titled people cannot ship without a supporting cast. Train for the work you want to be trusted with, not the word on the badge.
The through-line after twenty years
The job used to be “make the machine do the thing.” It became “make the organization able to keep doing the thing as the machine and the market change.” Coding is still the center of gravity. Everything else orbits it: product sense, communication, operations, ethics, and now AI-assisted speed.
If I train someone today, I train them to love the part that never gets obsolete: clear thinking under uncertainty, careful changes to living systems, and respect for the humans who have to live with what you ship. Languages will keep rotating. That core is what twenty years of being a programmer actually bought me — and what I would bet on again.