What changed after 7+ years of backend engineering in PHP, Go, and Python when I stopped typing every line by hand and built a role-based pipeline of AI agents.

2019 vs. 2026: Moving from writing every line by hand to running a role-based pipeline of AI agents.
In 2019 and 2020, my personal GitHub account averaged ~9 commits a month. Back then, I wrote every line by hand, spent evenings tracking down missing characters in my IDE, and handled every part of a feature myself, from database schema design to deployment.
Over the last 30 days in 2026, that same personal GitHub account logged ~700 commits (roughly 75x my 2019-2020 pace) and 328 merged pull requests across 14 repositories. Every commit came from a small, focused pull request with automated tests, and I typed almost none of the application code by hand.
After more than seven years of backend engineering in PHP, Go, and Python, my day-to-day work at a private marketing company in Thailand shifted from writing code myself to writing system specs, setting service boundaries, and running a role-based pipeline of AI agents. Below is how that pipeline works in practice, where agents break things when a spec is vague, and the CI and deployment checks I put in place to keep those repositories stable.
1. Writing Specs Instead of Hunting Typos

Why coding agents shift the effort from fixing syntax errors to writing unambiguous technical specifications.
When I first started using coding agents on backend services, I tried giving them short, two-sentence prompts and letting the model figure out the details. On a real codebase, that fell apart within a week. Coding agents rarely make syntax typos, so I no longer lose hours to a missing semicolon or an off-by-one loop counter. Instead, things break when a task description leaves an edge case open to interpretation.
A concrete example came up in my internal server fleet service, where I needed an endpoint to "probe the machine connection" and verify whether a remote host was reachable. Because my initial brief did not specify what should happen when a host is down, the agent had to guess: should the endpoint return HTTP 200 with an "unreachable" status saved in the database, or fail closed with HTTP 409? When five agents work on related tickets across parallel branches and the spec does not spell that out, each agent invents its own retry loop and status convention. At merge time, nothing fits together.
Because of that, I now review technical specs with the same care I used to put into code reviews:
- Which state transitions are valid, and which ones must be rejected?
- Which database fields are read-only metadata, and which ones represent server configuration that triggers an update when changed?
- What is the exact HTTP status code, error payload, and timeout for every failure path?
If I define those rules up front, the agents write clean, predictable code. If I leave a gap in the spec, five parallel agents will write five incompatible workarounds inside half an hour.
2. Why Backend Experience Still Drives the Architecture

Seven years of PHP, Go, and Python backend work now go into system boundaries, database performance, and failure recovery.
Before I built this workflow, I spent over seven years working on backend systems under production load. Over those years, I built order-lifecycle state machines handling thousands of orders a day, company-wide authorization and 2FA services handling thousands of requests per minute, and distributed VoIP telephony services covering contacts, billing, and call routing. A lot of that work meant profiling PHP and SQL queries down to the millisecond, tuning Elasticsearch indices for large-scale analytics reports, and splitting the heaviest domains out of monolithic Yii2 and CodeIgniter codebases into Symfony services and compiled, concurrent Go microservices.
I still rely on that exact same backend experience every day. Any decent model can generate a FastAPI endpoint, a Go binary, or an Alembic migration in ten seconds. What the model will not notice on its own is that a new query filters on an unindexed column that will lock a production table at peak traffic, or that an error handler might dump raw SSH keys or tokens into an application log.
The model handles the boilerplate and language syntax. Deciding where service boundaries sit, how state machines recover from partial failures, and how data moves between queues and databases is still on me.
3. Why One Long Chat Fails, and How My 5-Role Pipeline Works

How work is split across five distinct roles so no single agent gets lost in a long chat thread.
Early on, I tried doing everything inside a single long chat session: brainstorming the architecture, editing ten files, pasting stack traces, and debugging deployment scripts in the same thread. By turn twenty, the context window was full of abandoned ideas and contradictory instructions, and the model started undoing its own earlier fixes.
To keep each agent's context small and focused, I split the workflow into five separate roles, much like a regular engineering team:
- Architect (Me): I define the system architecture, service boundaries, data contracts, and security rules, and I do the final review before anything merges.
- Tech Lead Agent: Reads my initial task brief, inspects the target repository, and writes a detailed technical specification.
- Team Lead Agent: Breaks that approved spec down into small, self-contained GitHub issues with explicit acceptance criteria.
- 2 to 5 Developer Agents: Pick up individual issues on isolated Git branches, write the code and tests, and open pull requests.
- Review Agent and Automated CI: Check the pull request diff against the issue requirements and run the full test and migration suite before the PR reaches me for squash-merge.

From a voice note in a messenger to a reviewed, squash-merged pull request.
Each role only sees the artifact it needs: a spec, a single GitHub issue, or a pull request diff. No agent has to read through fifty messages of back-and-forth debugging history.
Most days, I start a task by sending a voice note in a messenger while away from my desk. An orchestrator service transcribes the audio into a draft brief, I review and approve the resulting spec, and the pipeline picks up the implementation. A full feature goes from voice note to merged PR in under 2 hours, and for small, well-defined changes, the whole loop finishes in 5 to 7 minutes.
4. Production Guardrails: What Changed After a Credential Rotation Froze a Deploy

Shipping ~700 commits and 328 pull requests in a month requires strict automated checks before anything reaches production.
When 328 pull requests land across 14 repositories in a single month, writing the code is no longer the slow part. The real work is making sure five parallel branches do not conflict on database migrations, expose internal ports, or leave a server half-deployed.
I learned this the hard way early on, when rotating a database and API credential froze a production deployment for hours because the deploy script relied on cached environment variables that had been set manually on the host months earlier. When one developer ships nine commits a month, manual server tweaks and "works on my machine" rarely hurt right away. When five developer agents push pull requests all day, any hidden state on a server will eventually break a release.

Every pull request runs against a clean Postgres container and port policy checks in CI.
Today, every repository in my stack runs four automated checks before code can reach production.
First, every pull request runs against a clean Postgres database in CI. The runner boots a fresh container, runs every schema migration from scratch (alembic upgrade head), and executes the test suite. If a migration fails on an empty database or conflicts with another branch, the PR is blocked automatically.
Second, CI renders the full Docker Compose configuration and checks port policies to make sure internal services never publish unintended ports on the host interface.
Third, agents never SSH into servers or run manual deploy commands. All deployments go through a deterministic, manifest-driven deployer that writes scoped secrets at runtime with 0600 permissions and checks /health/live endpoints before marking a release healthy.
Finally, no agent has permission to merge to main. Every squash-merge requires a green CI run and my sign-off on the diff.
5. Same Engineering Fundamentals, Different Layer

The daily work moved from typing syntax to defining architecture, specifications, and deployment checks.
Seven years of writing PHP, Go, and Python taught me how backend systems fail when traffic spikes, migrations lock tables, or network calls time out. Stopping hand-coding did not change any of those failure modes. It just moved my job up one layer: writing clear specs before any code is generated, keeping each agent in a narrow role, and letting automated CI and deterministic deployers catch mistakes before they hit production.
About the Author
Mykola (Nick) Skalenko is a Senior Backend Engineer and AI Solutions Architect with 7+ years of experience building distributed systems in PHP, Go, and Python. He currently designs and directs multi-agent engineering and automation systems for a private marketing company in Thailand.
- LinkedIn: Mykola Skalenko
- X (Twitter): @NikolaySkalenko
Top comments (0)