A customer support manager from a reputable fintech company uses Jira Service Management for time-bound, SLA-backed tickets, and Azure DevOps for the open-ended engineering work behind them. But the challenge was that the two systems never communicated.
When a support ticket became real engineering work, someone had to manually open a new work item in Azure DevOps, and then chase updates between the two tools over Teams until the work closed out.
But this lack of connectivity is a major drawback for enterprises across industries. So where does it all go wrong?
Where the Manual Handoff Breaks Down
Manual handoffs usually work for simple integrations that cover a limited scope. But with a bit of complexity, things fall apart.
That customer-reported bug stays in the backlog without any ongoing resolution. If the engineering team is working on it, the support team has no visibility into progress updates.
As a result, support agents end up pinging engineers directly for status updates, which defeats the point of tracking an SLA-bound ticket in the first place. The customer is left in the dark and likely gets more frustrated by the day.
What a Trigger-Based Connection Does Differently
Exalate connects Jira Service Management and Azure DevOps through a defined link that establishes sync rules between the two systems. These rules are controlled by Groovy scripts on each side.
These sync rules are also divided into incoming and outgoing:
- Outgoing sync rules decide what leaves Jira Service Management.
- Incoming sync rules decide how Azure DevOps receives it and maps it onto its own fields.
But to drill down to granular details, you can use Exalate triggers. This feature matters for support-to-engineering handoff, especially when it doesn’t require manual escalation.
Instead of syncing every ticket as soon as it's created, you add a condition to the outgoing sync rule so that only tickets that meet it get synced at all. Everything else stays in Jira Service Management and never touches Azure DevOps.
For example: a request type of "Development Required” will be automatically escalated to the devs.
When a ticket meets the condition, Exalate creates a replica: a linked work item in Azure DevOps that carries the fields you've mapped over. From that point on, the two are one synchronized pair, not two separately maintained tickets that happen to reference each other by a link in a comment.
How to Set Up the Trigger and the Field Mapping
The condition and the field mapping both live in the outgoing sync rule on the Jira Service Management (JSM) side. A simplified version looks like this:
// Outgoing sync rule (JSM side) if (issue.customFields.get("Needs Engineering Work")?.value != "Yes") { return null // don't create a replica for this ticket } replica.title = issue.summary replica.description = issue.description replica.workItemType = "Bug" replica.fields["System.Tags"] = "from-jsm" On the Azure DevOps (ADO) side, the incoming sync rule takes that replica and maps it onto real ADO fields like System.Title, System.WorkItemType, and System.Description. If your engineering team splits work by type, you can run a mapping tree similar to the issue-type translation Exalate uses elsewhere:
def issueMap = [ "Bug" : "Bug", "Task" : "Task", "Story" : "User Story" ] workItem.workItemType = issueMap[replica.workItemType] ?: "Task" You can layer in as much conditional logic as the scenario needs. It is possible to set up a connection that handles both a straight bug-to-bug escalation and a unique path that converts the bug to a User Story instead.
Attachments are also synced the same way as the initial fields, using the same replica object, so a screenshot the customer sent in with the original ticket shows up on the Azure DevOps work item without anyone re-uploading it.
If the engineering team wants the original reporter's contact details or the account name for context, they can map those to a custom field in Azure DevOps rather than leaving them buried in the Jira ticket.
What Happens After the Work Item is Created?
Creating the replica is easy, but setting it up for two-way sync is as complicated as it gets. If you want the Jira Service Management ticket and the Azure DevOps work item to stay linked for their whole lifecycle, here are some things Exalate can offer:
- Status changes on either side propagate to the other, once you've mapped JSM statuses to ADO states in the incoming sync rule.
- Comments sync through Exalate's comment helper, so an engineer's update in ADO shows up on the support ticket without a manual copy-paste.
- Attachments and worklog data carry across the same way, using the same field-mapping approach as the initial creation.
Exalate uses a proxy user to make these updates, so both systems clearly show which changes came from a person and which came from the sync.
Also, support agents can watch their SLA clock and see engineering progress without asking, and engineers get full support-side context without opening a second tool.
Before You Set This Up
Field mapping is straightforward and can be adjusted as you go. Deciding when a ticket actually deserves an engineering replica is a business call, and it's worth working that out with both the support lead and the engineering lead before anyone writes the Groovy for it.
So start with one request type or one label, get the trigger and the field mapping working end to end, and watch a handful of tickets go through the full lifecycle: creation, status changes, comments, and closure. Then, once you see it holding up, expand the condition rather than turning it on for your whole queue on day one.
If you're running Jira Service Management and Azure DevOps side by side and doing this handoff by hand today, this is exactly the kind of connection Exalate is built for. Reach out to us, and we can help you scope the trigger condition for your specific setup.