What Software Engineers Actually Do (And Why It's Not Going Away)

Pawel Zimoch · ~10 min read · Essay 08

There's an anxiety running through the software engineering profession right now. AI can write code. It's getting better fast. If the job is writing code, and AI can write code, what's left?

The anxiety is based on a misunderstanding of what the job actually is. This doesn't mean agents can't eventually match or surpass humans in all domains. But understanding where human engineers currently add value - beyond "just" writing code - clarifies both what's changing and what will take longer to automate.

Software engineers don't write code. They define structure. Code is just the medium - the way the structure gets expressed and executed. The medium is shifting. The work isn't going anywhere.

What Senior Engineers Actually Do

Watch a senior engineer work. They're not writing most of the code. They're doing something else.

They're in a design review, pushing back: "If we model it this way, we'll have to handle these edge cases everywhere. What if we made this state explicit instead?" They're sketching diagrams, mapping out boxes and arrows - not code, but structure. They're defining what entities exist, what operations are valid, what invariants must hold, where the boundaries are.

When they do write code, it's often the hardest parts - the interfaces, the state machines, the validation logic. The parts that define what the system is, not just what it does.

Junior engineers fill in the implementation. They write the functions, the handlers, the glue code. Important work, but work that happens within the structure the senior engineer defined.

The experienced engineer's value isn't their typing speed or syntax knowledge. It's their ability to look at a fuzzy problem and define the right structure - the abstractions that make the problem tractable, the boundaries that contain complexity, the invariants that prevent bugs.

This has always been the core of the work.

The Job Moves Up the Stack

Everyone is becoming more like the senior engineer.

When AI handles implementation, you spend less time writing the body of functions and more time deciding what functions should exist. Less time on syntax, more time on semantics. Less "how does this work," more "what should this system do and not do."

This isn't a reduction of the job. It's a concentration of it. The part that was always the hard part - defining the right structure - becomes the whole job.

Think about what this means in practice. Today, you might spend 30% of your time on design and architecture, 70% on implementation and debugging. Those percentages shift. Maybe it becomes 70% design, 30% review and refinement of AI-generated implementation.

The thinking doesn't decrease. If anything, it intensifies. You're doing more of the high-judgment work, less of the mechanical translation.

More Writing, Not Less Thinking

There's a catch, though. When a human implements your design, they fill in gaps. They share context with you. They ask clarifying questions. They interpret your intent when the specification is ambiguous.

AI doesn't do this the same way. It will fill gaps, but with hallucination rather than shared understanding. It will interpret ambiguity, but not necessarily the way you intended.

This means specifications have to be more explicit. The fuzziness that humans filled in now has to be written down. The hand-wave that worked with your team - "you know what I mean" - doesn't work with an agent.

So the job involves more writing. Not code, but structure. Specifications. Constraints. Descriptions of what's valid and what isn't. Schemas. State machines. Invariants expressed clearly enough that a machine can enforce them. The process of writing code itself becomes more structured: clearer explanations, established patterns, leveraging various tools to communicate intent to the agent and reduce the chance of errors.

This is harder than writing code, not easier. Code has a compiler that tells you when you're wrong. Specifications have only your own judgment and the failures that surface when the specification was incomplete.

The engineers who thrive will be the ones who can articulate structure clearly - who can take a fuzzy domain and produce a precise description of what exists, what can happen, and what rules apply.

The Foundations Matter More, Not Less

Here's what doesn't change: the fundamentals of computation.

State, events, and transformations. These are the atoms of all computation. Every system, no matter how it's built, reduces to: what state exists, what events can occur, and how events transform state.

Invariants. Properties that must always hold. An order can't ship without a delivery address. A balance can't go negative. Every reliable system is defined as much by what it prevents as by what it enables.

Valid transitions. Not every state change makes sense. A cancelled order can't become shipped. A resolved ticket can't go back to "new." The structure of valid transitions is the structure of the domain.

Error correction. Reliable systems make errors visible and correctable. This requires discrete states, explicit validation, observable outputs, and reversibility where possible. Shannon's insight about communication channels applies to any system that needs to work reliably.

Composition. Complex systems are built from simpler ones. How pieces fit together. Where boundaries are. What interfaces expose and what they hide.

These aren't "coding concepts." They're computational concepts. They apply whether you're writing Python, defining a database schema, or specifying a domain-specific language for agents to program.

When the surface syntax is handled for you, these foundations become more visible, not less relevant. You're working directly with the concepts that matter, without the syntactic noise.

An engineer who understands computation at this level can work with any medium - code, configuration, specification, natural language descriptions of structure. An engineer who only understood syntax is stranded when the syntax changes.

There's another implication: as agents make more systems computationally accessible, other professions will need to understand these basics too. The fundamentals of reliable systems - state management, error correction, clear interfaces - become a first-order concern for anyone building or specifying automated processes.

Domain Expertise Becomes the Differentiator

If structure is the work, then understanding the domain is the prerequisite.

You can't define the right entities without understanding what the business actually cares about. You can't specify valid transitions without knowing which state changes make sense in the real world. You can't set invariants without grasping what must never happen.

The engineer who understands the domain deeply - who knows which edge cases will actually bite, which states actually matter, which rules are load-bearing and which are incidental - that engineer becomes more valuable than ever.

This has always been true, but it was obscured. An engineer could hide weak domain understanding behind strong implementation skills. They could be "the person who writes fast code" without being "the person who understands what code to write."

That hiding place is disappearing. When AI writes the code, your value is the judgment about what code to write. And that judgment requires domain understanding.

This shifts what it means to be good at the job. Less "I know the syntax of six languages." More "I understand how supply chains work" or "I know what matters in healthcare billing" or "I've internalized the edge cases of payment processing."

The generalist who could learn any syntax quickly isn't obsolete. But they need to pair that learning speed with domain depth. The syntax matters less. The domain matters more.

The Craft Evolves, Not Disappears

Software engineering has been here before.

Engineers used to write assembly - managing registers, counting cycles, thinking in terms of machine instructions. Then compilers got good enough, and they wrote C instead. The assembly skills weren't "wasted" - they informed how to write efficient C. But the job moved up a level.

Then C gave way to higher-level languages. Python, JavaScript, Ruby. Garbage collection, dynamic typing, rich standard libraries. Again, the lower-level knowledge wasn't useless - it helped debug performance problems, understand what was happening underneath. But the daily work moved up a level.

Each shift "eliminated" the previous skill while requiring the same underlying judgment. The people who thrived weren't the ones who clung to assembly. They were the ones whose skills were rooted in computation itself, not in any particular expression of it.

This is another shift in the same pattern.

The medium changes from "code you write" to "structure you define and code AI writes." The underlying judgment - what to build, how to decompose it, what invariants to enforce, where the boundaries should be - remains yours.

Engineers who understand this will adapt the way engineers always have. The craft evolves. It doesn't disappear.

The New Equilibrium

If this analysis is correct, the shifts taking place have concrete implications:

Fundamentals gain importance. State machines, type systems, invariants, error handling—these concepts become more visible and more essential as implementation syntax fades into the background. Understanding them well enables work across whatever medium emerges. Skipping them in favor of "practical" skills leaves someone stranded when syntax changes.

Domain expertise becomes the differentiator. Translating fuzzy business needs into precise structure requires knowing the domain deeply: which edge cases actually matter, which rules are load-bearing, which state transitions make sense. Engineers who pair general technical understanding with domain depth define what gets built.

Specification becomes a craft. Writing things down precisely—schemas, state machines, interface definitions—becomes the core skill. Taking fuzzy requirements and producing unambiguous structure requires clarity of thought and communication. This is harder than writing code, not easier.

New tools require directed use. Understanding what AI coding assistants and agent frameworks can do, where they fail, and how to direct them effectively becomes necessary. The goal isn't resisting the shift but learning to drive these tools.

Avoid mistaking the medium for the work. Code has been the primary medium for expressing structure. It remains useful. But when implementation moves to AI, the engineer's work is defining what that implementation should do, not doing the implementation. Keeping this distinction clear makes the shifts navigable.

The Work Remains

There's a version of this moment that's terrifying: the machines are coming for your job, learn to code faster or be replaced.

That version is wrong, or at least badly incomplete.

The better version: the part of your job that was always the actual work - understanding problems, defining structure, making judgment calls about what should exist and how it should behave - is becoming the whole job. The mechanical parts are getting automated. The human parts remain.

This is not a small change. The daily texture of the work will shift. Skills that felt core will become peripheral. New skills will need to be developed. Some engineers will struggle with the transition.

But the discipline of software engineering - the practice of taking fuzzy human needs and defining precise computational structures to meet them - that discipline has a long future.

The machines need something to run on. Someone has to define what that something is.

That's the work. It's still yours.


This essay is part of a series on building reliable AI agent systems.

Overview: The Structure Problem

Previous: The Missing Scaffolding

Next: The Irreducible Human — Human irreducibility and open questions