How Zephyr made their add-on lightning fast

January 26th 2016 Shailesh Mangal (guest author) in Atlassian Connect, Add-ons

A major part of building add-ons for JIRA is the ability to show web fragments as an integrated part of pages within JIRA. This allows your add-on, via Atlassian Connect, to seamlessly integrate with JIRA. Getting JIRA to know when the right time to show these web fragments turned out to be a more complex and impactful problem than we expected.

Remote conditions were useful, but slow

You can conditionally load web fragments registered in your add-on's descriptor with remote conditions. On page load, JIRA will ping the URL endpoint registered in the remote condition, looking for a JSON payload returned with shouldDisplay as true or false. This controls if the UI will display your web fragment on the page.

It seemed like remote conditions could help us in dynamically controlling the display of our web fragments — but not quite. Every time JIRA loads a page with a web fragment, the remote condition is evaluated. We discovered that remote conditions impact the overall health and performance of our add-on because of how chatty they are. If our add-on is responding slowly, this in turns impacts the end user's experience with JIRA. And if the add-on becomes unavailable, waiting for requests to time out on every page load is a painful experience for the end user.

For each add-on with remote conditions an end user has installed, this problem is multiplied.

Traffic caused by remote condition

How we originally used remote conditions

For our add-on Zephyr For JIRA Cloud we have a few web fragments that show up on the ViewIssue page. We only want to show the fragment if the issue type is configured for it. To achieve this, we added a remote condition that checked the configuration stored in our add-on. JIRA invokes this remote condition with the current issue ID, which can be used to look up the issue details and discover the issue type. Then the remote condition can respond to the request with a true or false based upon the end user's configuration for that issue type. JIRA then decides to show the fragments based upon that response.

Sequence of events for each remote condition controlling a web section

In our first attempt to improve speed, we used caching

We soon realized that round trips are expensive. After we received the remote condition call from JIRA, we'd have to fetch the issue type from the issue and that caused even more latency. So, we started caching the issue responses. Caching solved the speed problem for previously viewed issues, but the latency persisted for new issues.

As our traffic grew, our add-on slowed

As we added more customers, traffic kept increasing. We were adding roughly three calls over the network per issue rendered in JIRA, even the issue types that weren’t of concern to us were getting impacted. Customers were complaining about our add-on dragging JIRA performance down. We reached out to the JIRA team who came out with conditions based on entity properties. We replaced our remote conditions with conditions based on entity properties.

Three web sections controlled by remote conditions

Bye-bye remote conditions, hello entity properties

Conditions based on entity properties provide a much better alternative to remote conditions wherever applicable. Entity properties let add-ons store arbitrary data on JIRA entities and conditions can leverage this data within the product. This eliminates the need for a remote call and provides better performance to the end user. This also reduces the bandwidth and computational needs for hosting your add-on.

In our case, we implemented the following steps:

  1. Add entity property on issue type. This property identifies if a current issue belongs to an issue type of interest. Setting the entity property is a one-time activity. Entity property operations are idempotent, so there is no harm creating the property multiple times.

    curl -X put -d “add-on-custom-property-value” -u admin:admin http://localhost:2990/rest/api/2/issuetype/1/properties/add-on-custom-property-name

    Note: For issue type, entity properties you can only add to existing entities and not at the time of entity creation.

  2. Replace remote conditions. All remote conditions from our atlassian-connect.json got replaced with normal conditions.

     {
       "condition": "entity_property_equal_to",
       "params": {
         "entity": "issuetype",
         "propertyKey": "add-on-custom-property-name",
         "value": " add-on-custom-property-value "
       }
     }
No remote call needed once entity properties implemented

After switching

By switching to entity properties, we eliminated all remote condition calls and reduced traffic to Zephyr servers by almost 80%.

Traffic reduced by 80%

Entity properties are your friend, use them

Remote conditions are powerful but they have a performance and scalability disadvantage. Entity properties along with conditions provide a compelling alternative. The transition to entity properties provided a significant savings in load and bandwidth. We recommend every add-on developer try to use entity properties before remote conditions.