Skip to main content

Managing Sync pipelines

Pause and resume​

Pause sits at the top of the pipeline's detail page, next to its status badge, and asks you to confirm before taking effect. Pausing stops the worker from consuming new events. Events aren't lost immediately: Auth0's own Events API retains them for up to 30 days, ready for FGA to catch up on once you resume. If the Sync pipeline stays paused longer than that, though, the events fall outside Auth0's replay window and are gone, and you'll need to reconcile them yourself (see Reconciling below).

Once paused, the Sync pipeline shows a Paused badge, and the header now offers Resume alongside Delete (Delete only appears once the pipeline is paused; see Delete a Sync pipeline below). Resuming also asks you to confirm, and continues syncing from the last cursor it had processed; events held during the pause are delivered and processed in order. The one exception is a pipeline paused long enough to lose that cursor to Auth0's own replay window; see the PAUSED_CURSOR_LOST row in the status reference below.

Change the model or mapping​

A mapping is only ever valid against a specific model, since the relations it writes to have to exist on that model. Both live on the same Mappings tab: a Model dropdown (with a view icon to inspect the selected model's schema) above the Mappings field. There's no separate model-picker flow; changing the model is just selecting a different one from that same dropdown.

To change either, update the dropdown selection and/or the mapping YAML as needed, then click Update Mappings.

Because your mapping may reference relations that don't exist on the newly selected model, saving re-runs the same mapping/model compatibility check from setup. If it fails, you'll see diagnostics so you can fix the mapping (or pick a different model) before saving; a failed validation has zero effect. The Sync pipeline keeps running exactly as it was, on its previous model and mapping, as if the save had never happened. See Validating a mapping file for what gets checked.

The worker picks up the change automatically, with no restart or downtime required.

caution

If your change renames or removes a relation the mapping previously wrote, as opposed to a purely additive change, there is currently a brief window where the old and new mapping could both process events: the worker finishing an in-flight event under the old mapping right as the new one takes over. For a purely additive change this is harmless. For a rename or removal, an event landing in that window can be processed under the old rules only, leaving a stale tuple under the new relation with nothing to fix it afterward.

Until this is addressed at the platform level, pause the Sync pipeline before saving a rename- or removal-style change, and resume it once the change is saved; see Pause and resume. Pausing first closes the window entirely, since nothing processes events while paused.

note

Mappings are not versioned today: updating a mapping overwrites it, with no history of prior versions and no built-in way to roll back. Keep your own copy of a mapping file before changing it if you want to be able to revert.

Delete a Sync pipeline​

A Sync pipeline must be paused before it can be deleted; pause it first if it's still active. Delete only appears at the top of the pipeline's detail page, alongside Resume, once the pipeline is paused; it's hidden entirely while a pipeline is Active. You're asked to type the pipeline's name to confirm, and this cannot be undone. Deleting stops the worker and removes the Sync pipeline's mapping and public key. The FGA tuples already written to your store are not affected; you manage those directly in FGA, independent of the Sync pipeline that created them.

After deleting, you're returned to the empty Auth0 Relationship Sync page, ready to set up a new one, for example to connect a different tenant.

Rotating credentials​

FGA imposes no expiration of its own on the signing key. The sole source of truth for how long it stays valid is your Auth0 client's own credential configuration: Never, From certificate, or a Custom date, set on the Machine-to-Machine application's Private Key JWT credential in Auth0. Auth0 does not send a notification ahead of any of these, so either set the expiration to Never and rotate on your own schedule, or set an actual date and configure your own reminder on the Auth0 side before it lapses; nothing on the FGA side will warn you.

Rotation is available on demand at any time; nothing on the FGA side forces it on a schedule.

A Sync pipeline keeps at most two keys at once: an Active key, and, while you're mid-rotation, a Candidate.

01. Generate a new key​

On the Credentials tab, click Generate New Public Key JWT. FGA generates a new RSA key pair and lists it as a Candidate, downloadable as an RS256 PEM certificate. This is the only time it's shown, so store it securely.

02. Add the new key to Auth0​

Upload the new PEM certificate to your Machine-to-Machine application as an additional Private Key JWT credential; see Auth0's Rotate credentials guide for the current steps. Auth0 supports multiple registered keys at once, so your current Active key keeps working while you do this.

03. Promote the new key​

Back on the Credentials tab, use the Candidate key's ... menu to promote it. This flips it to Active, and the worker immediately switches to signing with the new key. The key it replaces is relabeled Deprecated.

04. Remove the old key from Auth0​

Once the new key is confirmed working, remove the old key's credentials from your Auth0 application, then delete the Deprecated key from the Credentials tab's ... menu. You're asked to type the application's name to confirm, and this cannot be undone; the warning is scoped to the one key, not the whole Sync pipeline.

caution

A Sync pipeline needs a working Active key to authenticate. Confirm the new key is live in Auth0, and promoted, before removing the old one.

Reconciling​

Auth0 Relationship Sync processes events from the moment the Sync pipeline is activated; it does not import historical Auth0 data automatically. There are three situations where the FGA store can fall out of sync and require manual reconciliation.

note

Built-in reconciliation tooling is planned for a future release. For now, this is a self-serve process using the Auth0 Management API.

When you need to reconcile​

Initial setup: any Auth0 data that existed before the Sync pipeline was activated (users, organization memberships, role assignments, groups) is not in FGA. You need to populate it before going live.

Extended downtime: FGA has no queue of its own; whether you pause the Sync pipeline yourself or it's paused/disconnected automatically, the only thing standing between you and lost events is the Auth0 Events API's own retention window, bounding how far back a Sync pipeline can resume from.

note

This window is currently understood to be up to 30 days, but that figure is not yet officially confirmed for the Events API specifically; it's pending direct confirmation from the Auth0 platform team. (Auth0's separate Logs retention, which varies 1–30 days by plan, governs a different system and does not bound this Sync pipeline, so don't cite it as the source for this number.)

If this window is exceeded, the events inside it are gone and the Sync pipeline cannot replay them on resume. Treat it like an initial setup and reconcile from the Management API snapshot. This surfaces as the PAUSED_CURSOR_LOST status; see Sync pipeline status reference.

Mapping or model changes that affect synced tuples: see Change the model or mapping above for how to make the change itself; this covers when the change also requires reconciling tuples that were already synced. Not every change requires reconciliation. Only changes that alter how already-processed events produce tuples need it:

  • ✅ Requires reconciliation: renaming a relation, changing the user: or object: template in an existing rule, removing a rule that was previously writing tuples, changing role normalization logic.
  • ✅ Requires reconciliation: adding a new relation that should apply to existing Auth0 data (the Sync pipeline won't retroactively process old events to populate it).
  • ❌ Does not require reconciliation: adding a new rule for an event type that wasn't previously mapped (no old tuples to fix), adding a new relation type that your application populates directly.

Suspected drift, for any other reason: if you notice a permission that looks wrong, or otherwise suspect FGA has fallen out of sync with Auth0 without one of the specific triggers above, the same reconciliation approaches below still apply; there's nothing special about why you suspect drift. There's no dedicated drift-detection tooling today; start from How to reconcile below using the Auth0 Management API as the source of truth.

How to reconcile​

The general process: read the current state from the Auth0 Management API, translate it into FGA tuples, and write them to your store. There are two approaches.

Approach A (recommended): fga mapping run + fga tuple write. Export the current Auth0 state as a JSONL stream of synthetic events (one per user, membership, role assignment, etc.), feed it through your existing mapping file, and write the result to FGA:

your-management-api-export | fga mapping run mapping.yaml --aggregate --writes-only --format json > tuples.json
fga tuple write --store-id 01H... --file tuples.json

--aggregate reconciles the whole batch rather than streaming record-by-record, which matters when the same object appears in multiple exported records. Because this reuses the actual mapping file, the reconciliation logic can't drift from what the Sync pipeline itself does; there's nothing to keep in sync by hand. See Writing a Mapping File for the full CLI reference.

Approach B: direct FGA SDK writes. Read the current state from Auth0, compute tuples inline in a script, and write them to FGA using the SDK:

// Conceptual sketch
const members = await listOrgMembers(orgId); // Auth0 Management API
const tuples = members.flatMap(m => buildTuples(m)); // your logic
await fgaClient.write({ writes: tuples });

The mapping logic isn't reused here: you're re-implementing the same rules in your reconciliation script, so keep it in sync if your mapping file changes. Use this when Approach A's offline reconciler can't cover your case (see the caveat below) or when a genuinely custom transform is easier than reshaping data into the mapping engine's input.

Handling stale tuples after a mapping change​

If you are reconciling because your mapping changed, FGA may contain tuples written by the old mapping that are no longer correct. You have two options:

Clear first, then write new: delete stale tuples before writing the new ones. Avoids a mixed state with contradictory permissions, but causes a brief window where affected users have no permissions.

Write new, clean up after: write the new tuples first so users always have valid access, then identify and delete stale tuples. Safer for access continuity but risks a brief period where both old and new tuples coexist.

Which to prefer depends on whether the old and new tuples are contradictory (e.g., granting access where none should exist) or just redundant. Neither option has a universal "right" answer; match your application's tolerance for access gaps vs. overly permissive states.

A mapping's tuple_filters reconcile mode can help with the cleanup: if you can express the "desired state" for affected objects in your mapping, the read-diff-write mechanism will compute and apply the minimal set of writes and deletes automatically.

caution

This cleanup pattern relies on delete-by-filter rules (a tuple_filters entry without a fully-specified tuple), and fga mapping run can't resolve those offline; it needs a live FGA Read to know what a filter matches. Use Approach B for this specific cleanup, not Approach A. Approach A is safe for populating or backfilling state where every rule either writes a fully-specified tuple or deletes one.

Sync pipeline status reference​

StatusMeaningFix
PENDING_VERIFICATIONSync pipeline created but not yet active: missing a model and mapping, working credentials, or both.Select a model and mapping from the Mappings tab. See Troubleshooting.
ACTIVEHealthy; the worker is processing events normally.—
PAUSED_MANUALYou paused it yourself, from the top of the pipeline's detail page. This is the only paused state you can trigger on purpose; the rest below happen automatically when the worker detects a problem.Click Resume.
PAUSED_AUTH_FAILUREAuth0 rejected authentication, usually because the public key was removed or replaced in Auth0, or there's a mismatch between what FGA is signing with and what Auth0 has on file.See Troubleshooting.
PAUSED_KEY_EXPIREDA more specific case of an authentication failure: the Active credential's Auth0-side expiration has passed.Same fix as PAUSED_AUTH_FAILURE; see Rotating credentials.
PAUSED_POISON_EVENTA single event failed processing repeatedly, usually a malformed payload or a mapping bug. The worker stops rather than skip it, to avoid data inconsistency.See Troubleshooting.
PAUSED_CIRCUIT_BREAKERThis Sync pipeline's error rate crossed a threshold, protecting other Sync pipelines that share the same underlying worker.See Troubleshooting.
PAUSED_CURSOR_LOSTThe Sync pipeline was disconnected long enough that its last known position aged out of Auth0's event replay window and can no longer be resumed from.Click Resume; this resumes from the current time rather than the lost position, so reconcile any events missed in between. See Reconciling.
ARCHIVEDThe Sync pipeline has been deleted. Terminal state.—

Have Feedback?

You can use any of our support channels for any questions or suggestions you may have.