Why duplicates aren't rare — they're a systemic risk
When launching across dozens of accounts, a crash partway through is a statistically expected event: the network blips, Facebook returns a transient error, the process dies. A naive "press the button, run everything again" response duplicates work exactly where it already succeeded — and you often don't notice until Ads Manager suddenly shows double the budget on the same offer.
Where duplicates actually come from
The problem isn't the crash itself — it's having no memory of what was already done. If a process's state lives only in the running script's memory, it's lost entirely when it dies: the system doesn't know which account it stopped at, and on restart begins again at campaign #1 — even if campaigns #1–30 of 50 already exist for real on Facebook.
The fix: a log, a launch key, and reconciliation with Facebook
First, a database log, not memory: the result of every step (campaign X created on account Y — success/failure) is written right after it happens, not at the end of the run. On a crash and "Retry," the system reads the log and resumes where it stopped.
A log alone isn't enough. The trickiest case is an unclear outcome: the create request reached Facebook, but no response came back (network drop, timeout). The object may or may not exist — the log can't tell. So every step carries a launch key, and before retrying the system reconciles with Facebook: is there already an object with this key? If yes, it uses it and creates nothing new. If it can't tell for sure, it doesn't create a second one "just in case" — it flags the account: check Ads Manager. One question to a human beats a doubled budget.
What this means in practice for the user
- It's safe to click "Retry" several times in a row — a repeat call doesn't create new objects where they already exist.
- When a step's outcome is unclear, AdFleet doesn't guess: the account is flagged "check Ads Manager," and the call is yours.
- The launch log shows a status per account (success/failure), not one overall "done/not done" for the whole run — you see exactly what went wrong and where.
- Canceling a launch doesn't roll back what's already been created on Facebook — cancellation just stops going further; whatever already ran stays as is (a deliberate choice: rolling back real ad objects is a separate, riskier operation than simply stopping).