genv.

Running a hostSafe hosting provisioning, and how duplicates actually happen

12 min readPublished Reviewed By the GENV team

In short

Duplicates happen when a system retries a request whose outcome it never learned. The fix is to record the intent before sending it, reserve the account name in the same transaction, send an idempotency key the provider will honour, and treat "no answer" as a third outcome that stops and asks a person — never as a failure to retry.

Creating a hosting account is the riskiest thing a billing system does, for one structural reason: it is an effect on somebody else's machine, and you learn about it over a network that can fail after the effect and before the answer. Everything below follows from that single fact.

The three outcomes, and the one that is easy to forget

What a provisioning attempt can end as
OutcomeWhat it meansThe right response
SucceededThe provider confirmed the account existsRecord the reference and move on
RefusedThe provider said no, explicitlyRecord why, free the name, tell somebody
UnknownThe request went out and no usable answer came backStop. Hold the name, ask a person to look

Systems that model only success and failure have to force the third case into one of the first two. Forced into failure, it retries and you get two accounts. Forced into success, you bill for something that may not exist. Neither is recoverable automatically, because the system has thrown away the one fact that mattered: that it does not know.

Reserve the name in the same transaction as the intent

Before the request leaves, write down that you are making it, and claim the account name at the same time in the same database transaction. This does two things. It means a crash between deciding and sending leaves a record somebody can resolve. And it means a second request for the same name — a double-clicked button, a retried webhook, two staff acting at once — is refused by the database rather than by luck.

The claim must be keyed on the server and the account name, not on the connection record. Two connection rows can point at one machine: the same host typed with different capitalisation, or two sets of credentials made months apart. If your uniqueness rule is keyed on the connection, both can create the same account.

Send an idempotency key, and keep it stable

Where the provider supports it, send a key that identifies the logical command, and keep it identical across every retry of that command. A key derived from the attempt number, the clock or a fresh random value on each try is not an idempotency key; it is a guarantee of duplicates. Generate it once when the command is created, store it, and send the stored one.

Mark the moment before the effect

There is a meaningful difference between "the worker crashed while preparing the request" and "the worker crashed after sending it". The first is safe to retry and the second is not. You can tell them apart by committing a marker immediately before anything externally visible happens. A worker that dies before the marker can be recovered automatically; one that dies after it hands the case to a person.

Resolving an unknown outcome

  1. Look at the provider. Does an account with that name exist?
  2. If it does, check whether it is yours — whether your own system's marker is on it. A matching username is not proof; somebody else may have created an account with the same name.
  3. If it is yours, record that the creation had in fact happened. The account name stays claimed and the service is bound to it.
  4. If there is no such account, record that it had not happened. The name is released so it can be used again.
  5. Either way, the resolution is a recorded act by a named person, not a background job.

The second step is the one people skip. Adopting an account because the name matches is how a customer ends up managing somebody else's hosting. Require evidence of authorship — a marker your system wrote at creation — or require a person to acknowledge, in the request, that they are taking on an account you cannot verify.

Do not act on top of an uncertainty

If a service has an unresolved provisioning outcome, refuse the next effecting command against it. Suspending an account that may not exist, or resizing one you cannot confirm, turns one uncertainty into two. Reads are fine — looking is how the first one gets resolved.

How GENV implements this

This article describes GENV's actual design rather than an ideal. Outcomes are the five the connector contract defines, including an explicit ambiguous state; the account name is claimed in the transaction that authorises the command; uniqueness is enforced by database indexes keyed on the normalised installation and account name, with the connection deliberately left out of the key; and an unresolved outcome blocks further effecting commands until a person records what they found. Adoption of an existing account requires the provider's own proof of authorship, and taking on an account without that proof requires an explicit acknowledgement in the request.

Questions

Why not just check whether the account exists before retrying?

Because "an account with this name exists" does not tell you that your request created it. On a shared or reseller platform somebody else may have made it, and on your own platform a previous attempt may have. You need evidence of authorship, not existence.

Is an exponential backoff enough?

No. Backoff changes when you retry, not whether retrying is safe. A request that may have had an effect is unsafe to repeat at any interval.

What if the provider has no idempotency support?

Then you carry the burden: reserve the name, mark before the effect, and treat the unknown outcome as a stop. Several registrar and panel APIs have no idempotency mechanism at all, which is exactly why the local bookkeeping has to be right.

Sources

  1. cPanel & WHM — API documentation
  2. Enhance — orchd API reference

Official documentation, each requested on 21 September 2026. Provider behaviour changes; check the source before relying on a detail.