Azure DevOps as the Source of Truth(in case of conflict) in a Jira DC ↔ Azure DevOps Private/Public Connection

Hello Exalate Team,

I am integrating Jira Data Center and Azure DevOps using Exalate through a Private/Public connection.

One of the key requirements is around conflict management and data ownership.

Use Case

  • Jira DC and Azure DevOps are synchronized bidirectionally.
  • Azure DevOps should be considered the master system and the source of truth.
  • In situations where the same field is updated on both sides before synchronization completes, we want Azure DevOps values to take precedence.
  • Ideally, any conflicting changes coming from Jira should either:
    • be ignored, or
    • be overwritten by the Azure DevOps value during synchronization.

Questions

  1. Is it technically possible to configure Exalate so that Azure DevOps always wins during conflicts?
  2. If yes, what is the recommended approach?
    • Incoming sync rules?
    • Unidirectional field ownership?
    • Conditional synchronization logic?
    • Conflict detection using timestamps?
  3. Are there any best practices or examples for implementing a master/slave (source-of-truth) model in a Jira DC ↔ Azure DevOps integration?
  4. Does the fact that this is a Private/Public connection have any impact on conflict resolution behavior?

Thanks, Dhiren

Hi @Dhiren

Exalate has no built-in conflict detection at all, not even at the “last write wins” level. Incoming rules have no visibility into which side changed a field first, locally or remotely; there is no timestamp, version marker, or edit-order data passed between nodes by default. Each sync run simply applies whatever the rule maps, with no concept of “a conflict happened here.”

@Christophe_De_Beule I have been able to handle conflicts using the scripts provided here: Avoid updating issue with older changes ADO <> Jira, Jira <> Jira, ServiceNow <> Jira, ZenDesk <> Jira

@Dhiren although the scripts are not written such that ADO is always the winner, but it is a small customization that should get you there. Let me know if you still need a hand please.

Thanks

@Dhiren

You don’t need conflict detection at all — you prevent the conflict by making the ownership one-way per field.

For every field where ADO is the master, do the mapping in only one direction:

  • ADO outgoing → Jira incoming: apply the value normally.
    // Jira incoming (ADO is master → always overwrite Jira)
    issue.summary = replica.summary
    issue.description = replica.description
    issue.priority = replica.priority // etc. — everyADO-owned field
  • Jira outgoing → ADO incoming: for those same fields, do nothing — don’t map them back. Jira’s local edits simply never leave Jira / get reverted on the next ADO change.
    // ADO incoming: do NOT map the ADO-owned fields from Jira.
    // Only accept fields Jira is genuinely allowed to own (if any), e.g. a comment field.

Because Jira’s edit to an ADO-owned field is never sent, and the next ADO change overwrites Jira, ADO always wins by construction. No race, no timestamp math. This is the standard
master/slave pattern.

The reference provided by @Majid can work in case you want newest-edit-wins rather than strict ADO-master. And that can be achieved by Timestamp comparison

Thanks,

Sonal