Notes from a developer who uses AI coding assistants every day. Which jobs to hand over, which not to, the traps, and a safe way of working.
I use AI coding assistants every day, and I’m writing this because I’m tired of two extreme views. On one side, “developers aren’t needed anymore”. On the other, “it’s all nonsense, I wouldn’t trust a single line”. My experience sits somewhere in between, and I think it’s a more interesting place.
The best comparison I have: an AI assistant is a teammate who has read all the documentation in the world but is seeing your project for the first time. Very fast, never tired, and every now and then makes things up with great confidence. Which jobs would you give someone like that, and which wouldn’t you? The answer is about the same.
Short answer: I hand over work that repeats, is easy to verify and has a clear scope: boilerplate, test scaffolding, conversion scripts, explaining old code. I don’t hand over architecture decisions, security-critical code, irreversible database operations or the final approval. My rule is simple: I don’t merge code I don’t understand.
What I hand over happily
- Boilerplate: CRUD screens, form validation rules, migration files, API clients. Work with a known pattern where mistakes are easy to spot.
- Test scaffolding: “write tests for this function, edge cases included” usually gives a good start. Whether the tests actually test the right thing, I still check myself.
- One-off scripts: a script that cleans a CSV and imports it into the database, a hairy regular expression, an
awkone-liner. Code that runs once and gets thrown away is where the most time is saved. - Reading old code: getting a summary of what an inherited, comment-free, 2,000-line PHP file does. The model speeds up my reading; it doesn’t do the understanding for me.
- Text work: documentation, commit message drafts, translating interface copy. This site is bilingual, and I had a lot of help with first drafts of the English text; the final read is still mine.
What I never hand over
- Architecture and the data model: which tables exist, how services are split, what gets cached. These decisions need knowledge of the project’s business rules, and the price of getting them wrong is paid months later.
- Authentication, authorization and payment code: the model can write code here too, and it usually writes code that looks fine. That’s exactly the problem: it looks fine. I read this code line by line, the way I’d review a change sent in by a stranger.
- Irreversible commands:
DELETEorDROPon a production database,rm -rfon a server. The assistant can suggest them, but the decision to run them and the finger on the key are mine. - Secrets:
.envfiles, API keys, customer data. I don’t paste them into a chat window. If I need sample data, I generate fake data.
The traps I’ve hit
1. Packages and functions that don’t exist
Sometimes the model confidently suggests a function, or a Composer or npm package, that doesn’t exist. The nasty part: attackers have started registering package names that models often invent and filling them with malicious code. The trick even has a name now: “slopsquatting”. Before installing any new dependency it suggests, I look at the package page: who published it, how long it’s been around, how many people use it.
2. Stale knowledge
A model’s knowledge freezes at its training date. It may write an API the old way after a library changed it in a newer version. I state versions explicitly in my requests (“Laravel 13, PHP 8.4”) and check anything I’m unsure of against the official documentation.
3. Invisible security holes
The two I see most: SQL queries built by gluing strings, and missing authorization checks. The second is sneakier. Code that opens /invoice/42 without checking whether the user owns that invoice works, passes the tests and shows everyone’s invoices to everyone. I apply the list from the PHP security checklist to AI-written code exactly as I would to anyone else’s.
4. Silent behaviour changes
Ask it to “make this function more readable” and the model sometimes “fixes” an edge case too. An empty array that used to return null now throws an exception. Without tests you won’t notice. The customer will.
5. Too much code
There’s a tendency to write more than asked: an abstraction layer nobody wanted, three configuration options, an unnecessary interface. Every extra line is a line that will be read, maintained and may break later. Saying “write it shorter and simpler” often improves the result.
How I work
- Small pieces: instead of “write the invoicing module”, “write the migration that adds these columns to this table”. Small request, easy review.
- Give context: the versions I use, the folder structure, naming conventions. Many tools let you keep project rules in a file, and every rule I write there saves me fixing the same mistake for the hundredth time.
- Plan first: for a big change, I ask for the approach first and the code after. Catching the wrong path early is much cheaper than fixing wrong code later.
- Tests are a fence: in a project with tests, the assistant works far more safely, because whatever it breaks shows up immediately.
- Read the diff line by line: as if approving a colleague’s pull request. If there’s a line I don’t understand, I either ask about it or drop it.
- Small commits: each step its own commit, so rolling back is easy when something goes wrong.
So does it actually make you faster?
Yes, but not evenly. It speeds up the boring work a lot and the hard work not much. The hard part is still understanding the problem correctly, asking the right question and making the right decision. The assistant helps me turn those decisions into code faster; it doesn’t make them.
For clients, this means the routine parts can be delivered faster, but responsibility for the code still sits with the developer who delivers it. “The AI wrote it” isn’t an excuse. I stand behind every line I ship.
If you’re curious about another side of AI: how to write content that AI answers cite as a source.