ai

Failed Sync Retry: Recover Reverse ETL Failures With an AI Agent on Rails

A reverse ETL failed sync retry is safe only when it repeats the same approved version, audience hash and destination, with an idempotency key and a fresh consent check. A Sync Medic agent starts at L3, where on-call approves each retry, and can reach L4 for this bounded case on a customer data platform (CDP). Anything else needs approval.

Rail level: L3 to L4 · Risk: medium · Function: platform operations

By Art Kukharenko · Published · Updated

All AI agent rails

Who this is for: platform leads and data engineers who run audience syncs under an approval process. This job is one rail in the vendor-neutral AI agent rails method. Tool behaviour below comes from vendor documentation read on 1 November 2026.

Before: the manual workflow

The manual workflow for a failed sync is an on-call engineer reading logs and deciding whether to press retry. An alert fires, or a marketer notices a low count. The engineer opens the run, guesses whether the error is transient, and re-runs it or forces a full resync. Nobody checks whether the audience has changed since it was approved. Duplicates appear days later as a complaint, or not at all.

Reverse ETL tools already retry a lot of this themselves. So the human question is narrower than it looks: what happens when the built-in retries stop, and does a re-run still match what someone approved?

When is a retry not a new activation?

A retry is not a new activation only when nothing a person approved has changed. The rule has four tests: same approved version, same audience hash, same destination, and consent re-checked. This table turns it into decisions.

What changed since approvalTreat it asWho acts
Nothing, and the error is transientBounded retrySync Medic, within limits
Some people withdrew consentThe same retry with a smaller setSync Medic; the removal count is logged
People were added, or the hash differsNew activationA named approver
Field mapping or sync modeConfiguration changePlatform on-call, after a proposal
Destination or accountNew activationA named approver; the allow-list still applies
Retry limit or window exceededStopPlatform on-call
Approval expiredNew activationA named approver

Consent can only shrink a retry. Anything that grows the set voids the approval, because approval binds to a hash of the exact payload. This needs a frozen copy of the approved audience. If the sync recomputes from a live model, you cannot prove the audience is the same, so point it at a versioned snapshot table instead.

Why do retries cause duplicate deliveries?

Retries cause duplicates because the caller often cannot tell whether the first attempt worked. AWS's engineering guidance describes the core case: when a response is lost, the caller does not know the outcome, and a blind retry can repeat the effect 1. Batches make it worse. Airbyte states that it delivers at least once, and that a partly completed chunk may be re-sent on the next attempt 2. Hightouch and Fivetran Activations can both split a rejected batch and retry the parts 34.

In a warehouse, a duplicate is usually a clean-up task. In a destination, it can reach a person. So the destination's operation sets the highest level a retry may run at. The levels below are our recommendation.

Destination operationEffect of a repeatDuplicate riskHighest level
Add to a list or audienceMembership stays the sameLowL4
Upsert on a stable external IDConverges on one recordLowL4
Event with a destination dedupe keyDiscarded inside the window. Meta dedupes on event ID and name within 48 hours 5Low inside the window, high after itL4 inside the window, otherwise L3
Create or insert with no keyA new row each time. Fivetran's function connectors insert new rows when no primary key is set 6HighL3, and fix the design
Mirror with removalsMay remove on stale data. Mirror compares with what was sent, not the destination 7MediumL3
Journey entry or message triggerA person may be contacted twiceHigh, and it cannot be undoneL3 at most, or manual

An idempotency key closes the lost-response gap where the destination supports one. The same key goes on every attempt. AWS says a known token with different parameters should return a validation error, which is what you want if a payload has drifted 1. Stripe's documentation, a useful reference pattern though not a marketing destination, advises against personal data in keys and says keys can be pruned once at least 24 hours old 8. The lesson is general: the retry window must be shorter than the destination's key or dedupe window.

After: the job on rails, step by step

The failed sync job on rails puts a rules engine on the action path and a model on the explanation.

  1. A failed sync event arrives. Include partial failures. Hightouch ends a run with rejected rows as "Completed with errors", not "Failed" 3, so an alert on failure alone misses them.
  2. Rules classify the error. Timeouts, 5xx and 429 are transient. Authentication and validation errors are not, as both Hightouch and Fivetran's connector guidance treat them 39. The agent holds no keys, so a 401 goes to on-call.
  3. Rules compare against the approval. They check approval hash, snapshot hash, destination, mapping version, operation type, retry count and window.
  4. The consent service runs a fresh check. Withdrawn people drop out of the set, using the same enforcement as a send-time check. The check ID is stored.
  5. The execution service retries. It reuses the key, backs off with jitter, and honours Retry-After 4. At L3 it waits for on-call to approve. At L4 it proceeds.
  6. Rules reconcile. Accepted counts are compared with the expected set. A mismatch stops further retries.
  7. The model explains. It writes the likely cause for on-call and proposes a fix for anything that is not a retry. It holds no retry tool.

Promotion from L3 to L4 needs written evidence and the platform lead's sign-off. Replay past failures in a test destination and find no duplicates. Show that a changed hash blocks the retry and that a withdrawal removes the person. Drill the kill switch. Any breach drops the rail back automatically, as the rail levels require.

L4 also expects reversibility, which limits this rail honestly. A retried list add can be removed using the approved sync's rollback reference. A sent message cannot. So on a failed reconciliation, retries stop and the rail falls to L3, and on-call decides on any removal. Destinations that cannot be reversed never run at L4.

What rules do and what the model does

Rules make every retry decision here, and the model only writes the explanation. Error text from a destination is outside input, and it could contain instructions. The Rule of Two says a session should not hold untrusted input, sensitive access and state-changing tools together 10. So the model reads logs without payload data and has no tools that change state. The action path has no model in it, and a hijacked explanation cannot trigger a retry.

TaskDone by
Classify the errorRules
Compare hash, version and destinationRules
Check consentConsent service
Retry, back off, use the keyExecution service
Reconcile countsRules
Explain a likely causeModel
Propose a fix for anything elseModel proposes; platform on-call approves

The rail card

The rail card below fixes what Sync Medic may do. Retry limits and windows are yours to set, within the dedupe window above.

FieldValue
JobDiagnose failed syncs, retry an already approved sync within limits, and propose other fixes.
TriggerA failed sync event, including partial failure.
Data scopeSync logs, error codes and the approval record hash. No payload data.
Tool scopeRead: sync logs, error codes, approval record, destination status. Propose: a fix for anything other than a retry. Execute: retry the same approved sync version with idempotency and a fresh consent check.
Output contractFailure cause, retry record, or a fix proposal.
GateNo new approval for a bounded retry of the same approved hash. The platform on-call approves any other change.
LimitsRetries per sync, backoff, same destination and audience hash only.
LedgerSync ID, approval hash, retry count, consent-check ID, outcome.
EvaluationReplay of historic failures in a test destination.
Owner and kill switchPlatform lead. Disable retries, and failures go to on-call.

The first sync still belongs to the Audience Sync Steward, with a named approver bound to the segment hash, as in the segmentation walkthrough. Sync Medic only repeats what that approval covered.

What the ledger shows for one run

The ledger entry for one retry shows that nothing approved has changed. This example is illustrative, with invented values and no personal data.

{
  "sync_id": "sync_4471",
  "rail": "sync-medic@v2",
  "level": "L4",
  "error_class": "destination_5xx",
  "approval_hash": "9f2c...",
  "audience_hash": "71de...",
  "destination": "ad_platform_a",
  "mapping_version": "v12",
  "retry": {"count": 2, "limit": 3, "key_ref": "idem_8841"},
  "consent_check_id": "cc_7712",
  "removed_by_consent": 14,
  "reconciliation": "match",
  "outcome": "accepted"
}

Three ways it fails, and the control for each

Each failure below is a known pipeline problem, and each control sits outside the model.

FailureWhat it looks likeControl
Duplicate deliveryA lost response leads to a second send, or a partial batch is re-sent to a keyless endpoint.Allow L4 only for operations in the safe rows above. Reuse keys. Reconcile after each run.
Retry stormAn outage or rate limit gets worse because the tool retries and the agent retries too. AWS's example of five layers with three retries each gives about 243 times the load, so it advises retrying at one point in the stack 11.Let one layer own retries. Use backoff, jitter and a budget, then stop.
A changed audience passed off as a retryThe next scheduled run picks up new rows, or a withdrawal is missed because the check is stale.Compare hashes against a frozen snapshot. Require a fresh check ID on every attempt.

Metrics that are honest

Honest retry metrics count harm as well as speed.

  • Mean time to recover, from failure to reconciled delivery.
  • Duplicate deliveries, target zero. Measure them in seeded replays and through reconciliation, because production duplicates are easy to miss.
  • Failed retries, which show whether error classification is right.
  • Retries refused by rule, split by reason. A rise may show approvals expiring too fast.
  • Audit coverage. Any retry without a complete record is a defect.

How vendor tools compare

Reverse ETL and pipeline tools handle retries well, and their defaults are often all you need. We read these pages on 1 November 2026. They do not address approval binding, which is not their job.

ToolDocumented retry behaviourStated limitOn duplicates
HightouchIn-run backoff, up to five attempts by default. 400, 401, 403 and 422 are rejected without retry, and 429 gets more attempts. Rejected rows retry on later runs by primary key 3.No attempt limit across runs; a row stops when it succeeds or leaves the model's results 3The retries page is silent
Fivetran Activations (formerly Census)In-run backoff, batch splitting, Retry-After honoured. Rejected records retry on later runs by primary key 4.No maximum stated 4The page is silent; behaviours include Create Only and Mirror 7
AirbyteRetries and resumes from committed state. An ingestion tool 2.Retries while progress continues 2At least once. Choose a mode with deduplication 2
Fivetran connectorsConnector SDK guidance: retry transient errors, fail when data integrity is at risk 9. An ingestion tool.Set by your codeFunction connectors are expected to be idempotent 6

One detail matters for approvals. Hightouch compares current model results with the previous run 12, so a later run may carry new rows alongside the retried ones. As we read it, that is closer to a new run than to a retry of what was approved. A frozen snapshot table avoids the question.

A vendor's retry plus an alert is enough when the destination upserts, the audience has no approval bound to it, and the data is low-risk. Where approval does apply, a script can do everything on the action path, because that path has no model anyway. Add the model only if on-call wants a written diagnosis. PrivyCDP's immutable audit ledger records each AI-assisted action with the human or system actor that authorised it; Sync Medic itself is a method you would build, not a shipped feature. The rule on approval gates still governs anything outside the bounds.

Checklist

  • Alerts fire on partial failure as well as failed runs.
  • Syncs read a frozen snapshot, versioned by audience hash.
  • Rules classify errors, and authentication failures go to on-call.
  • Hash, version, destination and mapping are compared before each attempt.
  • A fresh consent check runs on every attempt, and it can only shrink the set.
  • Each destination operation has a written highest level.
  • Keys are reused across attempts and contain no personal data.
  • The retry window is shorter than the key or dedupe window.
  • One layer owns retries.
  • Reconciliation follows every retry, and a mismatch stops the rail.

The wider function is in the platform and data pipeline operations playbook, and the method is on the AI agent rails hub. To write this rail for your team, download the rail card template.

Browse use casesFunction playbooksAgent roster

FAQ

What is a failed sync retry in reverse ETL?

It is a repeat of a data delivery from a warehouse or customer data platform to a destination after an error. Tools retry rejected rows in the same run and on later runs. On a rail, a retry means something stricter: the same approved version, audience hash and destination, with consent re-checked.

How do you avoid duplicates when retrying a sync?

Prefer operations that converge, such as list adds and upserts on a stable ID. Reuse one idempotency key across attempts where the destination supports it, and keep the retry window inside its dedupe window. Reconcile counts after each run. Treat keyless inserts and message triggers as manual decisions, because a repeat may reach a person.

Does a retried sync need a new approval?

Not if nothing approved has changed and limits are met: same version, hash and destination, with a fresh consent check. Consent may remove people, but nobody may be added. A changed audience, mapping or destination is a new decision, so it needs a named approver or platform on-call, depending on the change.

Consent can change between the first attempt and the retry, and the original check only described that earlier moment. A withdrawal must take effect wherever the data goes next. A retry therefore needs its own check ID in the ledger. The check can remove people from the set but never add them.

Can an AI agent retry a sync on its own?

Only within written bounds, and only after a period at L3 with evidence and owner sign-off. Even then, rules make the decision and an execution service acts. The model writes the explanation and proposes other fixes. Destinations where a repeat cannot be reversed, such as message triggers, stay with a person.

What is the difference between a rejected row and a failed run?

A rejected row is one record a destination refused, while the rest of the run continued. A failed run stopped as a whole, for example on a query or authentication error. Hightouch reports a run with rejected rows as completed with errors. Monitor both, because the partial case is the one alerts tend to miss.

Sources

  1. AWS Builders' Library, Making retries safe with idempotent APIs
  2. Airbyte, resumability
  3. Hightouch, retries
  4. Fivetran Activations, retry handling
  5. Meta, handling duplicate Pixel and Conversions API events
  6. Fivetran, function connectors
  7. Fivetran Activations, syncs
  8. Stripe, idempotent requests
  9. Fivetran Connector SDK, error handling
  10. Meta, Agents Rule of Two (31 October 2025)
  11. AWS Builders' Library, Timeouts, retries and backoff with jitter
  12. Hightouch, syncs overview

This article is general information, not legal advice.

Further reading

Published: · Updated:

Editorial dates describe content changes. Confirm current sources before making legal, security or purchasing decisions.