Habr author lists five decisions an engineer must make before AI writes the code

A new Habr post looks at which engineering decisions need to be made before an AI agent starts writing code. The starting point is a bug in a marketplace's payment handler: two simultaneous webhooks both passed the PENDING check, and the money was credited twice. The author wrote that code himself, without AI. He walks through five situations from two projects: payment idempotency, data migrations, message delivery between service instances, provider integrations, and brand architecture. The result is a checklist of 12 questions. - The agent builds what the description says, and concurrency usually isn't in the description - Five risk areas: payments, migrations, messages, providers, brands - Run through 12 questions before generating code

AI-processed from Habr AI; edited by Hamidun News
Habr author lists five decisions an engineer must make before AI writes the code
Source: Habr AI. Collage: Hamidun News.
Listen to article
Article Fact Sheet & Key Figures
ParameterDetails
Primary sourceHabr AI ↗
Editor-in-Chief
Key metric #1The agent builds what the description says, and concurrency usually isn't in the description
Five risk areaspayments, migrations, messages, providers, brands
Key metric #3Run through 12 questions before generating code

One of the nastiest bugs in payment logic looks harmless: check that the operation is in PENDING status, move it to SUCCESS, and credit the balance. If two webhooks arrive at the same time, both see PENDING, both pass the check, and the user gets the money twice. The author of a recent Habr post found exactly this bug in his own marketplace. He wrote the code himself, without AI.

He uses this example to ask the central question: if an agent can now implement a handler like this in minutes, who sets the constraints that the functional description leaves out? The author then goes through five situations from a marketplace and a multi-brand platform, and closes with a checklist of 12 questions to work through before generating code.

Where the spec is silent

An agent does well what is described. The phrase "credit the balance on a successful webhook" is formally satisfied by both a correct implementation and a vulnerable one. The difference shows up only under parallel load, and a single-threaded test won't reveal it.

This is not a property of language models but of any task statement that omits non-functional requirements. A human usually fills the gap with experience and memories of past outages. An agent has no way to get that context unless it is passed in explicitly.

The author identifies five areas where such decisions need to be made in advance:

  • payment idempotency: what counts as a repeated request and where that is guaranteed;
  • data migrations: the order of changes and how the system behaves in intermediate states;
  • message delivery between service instances: what happens if the recipient is the wrong one or is unavailable;
  • provider integrations: how the system behaves with retries, delays, and non-standard responses;
  • brand architecture: what is shared across all of the platform's brands and what is configured separately.

The author gives the full list of 12 questions in the original article. One caveat: the announcement doesn't include details of the solutions, so what follows describes how the industry usually handles such problems, not the author's conclusions.

How this is usually solved

The standard set of measures for the webhook problem is well known. A unique event key or an idempotency key on the request. An atomic conditional update of the form "move to SUCCESS only if the status is still PENDING," plus a check of the number of affected rows. A row lock held for the duration of the transaction. Any of these turns "check, then write" into a single indivisible operation.

The logic is similar for migrations and messages. Schema changes have to work while the old and new versions of the service run side by side. Delivery needs an upfront agreement on whether losses and duplicates are acceptable. These decisions shape the structure of the code, so making them after generation is already expensive: you will have to rewrite, not add on.

How to use this in practice

If you hand a task to an agent, attach a short block of constraints. What must stay true on a repeated call? On two parallel calls? On a partial failure of an external provider? When a new version is rolled out next to the old one?

It also helps to ask the agent not only to write the code but to list the assumptions it made about concurrency and event ordering. The gap between its assumptions and yours is the fastest way to find a hole in the task statement.

Finally, tests. A payment path needs at least one test with simultaneous requests; otherwise correctness is checked only at the "looks right" level. That is exactly how the handler looked in the author's story: the logic read as correct and broke only in a race.

The article's conclusions apply to human-written code as well. AI speeds up implementation, but decisions about the system's invariants still have to be made before it, and an engineer makes them.

Story

Key Questions Answered

Where the spec is silent?

An agent does well what is described. The phrase "credit the balance on a successful webhook" is formally satisfied by both a correct implementation and a vulnerable one. The difference shows up only under parallel load, and a single-threaded test won't reveal it. This is not a property of language models but of any task statement that omits non-functional requirements. A human usually fills the gap with experience and memories of past outages. An agent has no way to get that context unless it is passed in explicitly. The author identifies five areas where such decisions ne

How this is usually solved?

The standard set of measures for the webhook problem is well known. A unique event key or an idempotency key on the request. An atomic conditional update of the form "move to SUCCESS only if the status is still PENDING," plus a check of the number of affected rows. A row lock held for the duration of the transaction. Any of these turns "check, then write" into a single indivisible operation. The logic is similar for migrations and messages. Schema changes have to work while the old and new versions of the service run side by side. Delivery needs an upfront agreement on whet

How to use this in practice?

If you hand a task to an agent, attach a short block of constraints. What must stay true on a repeated call? On two parallel calls? On a partial failure of an external provider? When a new version is rolled out next to the old one? It also helps to ask the agent not only to write the code but to list the assumptions it made about concurrency and event ordering. The gap between its assumptions and yours is the fastest way to find a hole in the task statement. Finally, tests. A payment path needs at least one test with simultaneous requests; otherwise correctness is checked o

ZK
Zhemal Khamidun — CPO at Alpina Digital, product manager of AlpinaGPT. Building AI products since 2019. Hamidun News is a pet project that grew into a production aggregator with 6,000+ readers.
✦ Autonomous AI Agents

Delegate Deep Research, Coding & Workflows to an AI Agent

Deploy autonomous multi-step execution with NomadNet Agent (agent.nomadnet.ai) — automated web research, data synthesis, code generation, and complex task orchestration.

Launch NomadNet Agent →NomadNet AI Platform
What do you think?
Loading comments…