← All writing

What should your coding agent never build from scratch?

Sign-in, payments, email deliverability, and keeping customer data separate. Four things where generated code looks right, passes review, and fails later.

What should your coding agent never build from scratch?

Four things: sign-in, payments, email deliverability, and the separation between one customer's data and another's. Not because an agent writes them badly, but because it writes them plausibly. In all four, the difference between correct and dangerous is invisible in a code review and only shows up under conditions you will not think to test. Everything else is fair game.

Here is why each one earns its place on the list.

The pattern that connects them

A coding agent is very good at producing code that looks like the code it has seen. For most work, that is exactly what you want. Its output resembles a competent version of the thing, and where it is wrong, the wrongness is visible: the button is in the wrong place, the calculation is off, the test fails.

These four are different. In each one there is a version that resembles the correct implementation in every respect a reader would check, and differs only in a detail that has no visible effect until a specific, unusual thing happens. There is no failing test, because the test you would have written passes. There is no error in the logs, because nothing errored.

That is the category. Not "hard", but "wrong in a way that looks fine".

1. Sign-in

Ask for authentication and you will get sessions, a login form, and probably social sign-in. It will work. You will log in with it.

What is hard is the set of cases nobody demonstrates:

  • Somebody signs up with email, then later signs in with Google using that same address. Do they get their existing account, or a silent duplicate that has none of their data? Both are one line of code apart, and only one of them is right.
  • A sign-in code arrives by email. Does it expire? How many guesses does someone get? Is the comparison timing-safe? Is the code stored as a hash, or in a column that ends up in a log?
  • The session cookie: is it marked secure, http-only, same-site? Does signing out actually invalidate the session on the server, or just drop the cookie?
  • Somebody requests fifty sign-in codes for an address that is not theirs. What stops that?

Each of these is a couple of lines. None is visible in the demo. The account-merge one in particular produces a bug report that reads "I lost all my data when I logged in", six weeks after launch, and by then there are real duplicate accounts to reconcile by hand.

2. Payments

The checkout is the easy half, and it is the half that gets built. Money moves. It looks finished.

The hard half is everything after the customer pays:

  • The webhook is the source of truth, not the redirect. A customer who closes the tab during redirect has still paid. If your subscription record is written on the success page, that customer is charged and has nothing.
  • Signature verification. Without it, your endpoint accepts a subscription record from anyone who can find the URL. There is no error state for this. It just works, for everyone, including people who did not pay.
  • Duplicate delivery. Payment providers retry, and they deliver the same event more than once by design. If handling an event twice does anything other than what handling it once did, you will find out during an outage, when retries are heaviest.
  • The passage of time. Cards expire, payments fail, subscriptions lapse, refunds and chargebacks happen. Access has to follow all of that without anyone at a keyboard.

An agent asked to "add subscriptions" produces the checkout, and often a webhook handler. Whether that handler verifies signatures and tolerates duplicates is not something you can see by reading it next to a correct one. They look the same.

3. Email deliverability

This is the one people are most surprised by, because the code is genuinely trivial. Send an email. Two lines. It works, and it arrives.

Then you launch on your own domain and roughly a third of your mail goes to spam, including your sign-in codes, which means new customers cannot get in and you have no error to look at.

Deliverability is almost entirely not code. It is DNS records, and getting them subtly wrong is the default state:

  • SPF says which servers may send for your domain.
  • DKIM signs your mail cryptographically.
  • DMARC tells receivers what to do when a message fails the first two. This is the one people skip, because mail appears to work without it, and receivers increasingly treat its absence as a reason for suspicion.
  • The From address has to be on the domain you verified. Sign with one domain and claim another in the From header and alignment fails, which is exactly the pattern spoofing filters exist to catch.

Your agent cannot fix this by writing better code, because the code was never the problem. It is covered properly in email that reaches the inbox.

4. Keeping customer data separate

The most consequential item, and the most boring to look at.

If your product has accounts, then every query that reads customer data has to be limited to the account making the request. Every single one. The failure mode when one is missed is that a customer sees another customer's data.

The reason this is dangerous with generated code is arithmetic. A missing filter is one clause in one query. It has no symptoms in development, because you have one account and everything you can see is yours. It has no symptoms in your tests, unless you specifically wrote a test with two accounts. Your app is faster without it. Nothing anywhere is red.

The only reliable defense is a structure where scoping is the default rather than a thing you remember: queries go through the current account rather than through the model, permission checks default to denying, and every resource ships with a test that a request for another account's record returns a 404. That is a convention, not a feature, and conventions are exactly what an agent building from an empty directory has no way to inherit. More on the mechanics in keeping every customer's data separate.

What agents are genuinely excellent at

This list is short on purpose, and it is worth being clear about the other side.

Coding agents are extremely good at everything downstream of these four: your data model, your screens, your business rules, your integrations, your admin tooling, your tests. Give one a codebase with clear conventions and a test suite and it will produce work that is careful, consistent, and faster than you would be. That is the whole point.

The four above are not a limit on what agents can do. They are a specific category where "looks correct" and "is correct" come apart, and where you personally will not catch the difference by reading the diff.

The practical version

Do not ask your agent to avoid these. Give it a codebase where they already exist, are tested, and have a written convention it can follow. Then the agent spends its entire run on the thing you actually hired it for, and it can check its own work, because there is something to run.

That is the argument for starting from a kit at all, and it is most of where your first agent run actually goes.

Keep reading