Tuning webhook performance parameters in Jira Data Center

Still need help?

The Atlassian Community is here for you.

Ask the community

Platform Notice: Data Center - This article applies to Atlassian products on the Data Center platform.

Note that this knowledge base article was created for the Data Center version of the product. Data Center knowledge base articles for non-Data Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

In Jira 9 and earlier, webhooks are processed synchronously, with the most computationally intensive work performed during the HTTP request. Administrators can opt-in to asynchronous webhooks by adding a feature flag and performing a rolling restart.

Starting in Jira 10.0.0, asynchronous webhooks have become the default and only option. This change significantly enhances the end-user experience, as processing is now handled by a dedicated thread pool instead of being tied to the user request.

However, in both Jira 9 and 10, environments with exceptional webhook usage may exceed the guardrails set by the default parameters. The following parameters allow you to customize these limits to meet your organization’s needs.

Environment

Jira Data Center 10.3.5 LTS / 10.6.0 and later.

These parameters are unavailable in Jira 10.0.0-10.3.4 LTS / 10.4.0-10.5.0. Please upgrade to the current LTS bug fix release or the latest feature release. For more details, please consult the Jira Software release notes and Upgrading Jira applications.

For all versions of Jira Data Center 9, please review the workarounds on JRASERVER-74492 - Getting issue details... STATUS .

Diagnosis

Problem 1: processing queue

You observe the following error in your atlassian-jira.log file:

2025-03-25 14:05:00,000+0000 http-nio-8080-exec-1 ERROR charlie 1x1x1 abcdef 0.0.0.0 /secure/AjaxIssueAction.jspa [c.a.event.internal.AsynchronousAbleEventDispatcher] There was an exception thrown trying to dispatch event [com.atlassian.jira.event.issue.IssueEvent@cafebabe[issue=TIS-1,comment=<null>,worklog=<null>,changelog=[GenericEntity:ChangeGroup][issue,10000][author,charlie][created,2025-03-25 14:04:59.00][id,10000],eventTypeId=2,sendMail=true,params={eventsource=action, baseurl=https://jira.example.com},subtasksUpdated=true,spanningOperation=Optional.empty]] from the invoker [com.atlassian.event.internal.ComparableListenerInvoker@cafebabe]
java.lang.RuntimeException: Task com.atlassian.webhooks.internal.DefaultWebhookService$$Lambda$1234/0x0000000cafebebe@cafebabe rejected from java.util.concurrent.ThreadPoolExecutor@cafebabe[Running, pool size = 5, active threads = 5, queued tasks = 250, completed tasks = 80000]. Listener: com.atlassian.jira.plugins.webhooks.spi.JiraWebhookEventPublisher event: com.atlassian.jira.event.issue.IssueEvent

Simplified:

Task rejected from ThreadPoolExecutor[Running, pool size = 5, active threads = 5, queued tasks = 250, completed tasks = 80000]

Problem 2: HTTP dispatch queue

You observe the following error in your atlassian-jira.log file:

2025-03-25 14:05:00,000+0000 webhook-dispatcher:thread-1 WARN anonymous     [c.a.w.internal.publish.DefaultWebhookDispatcher] Could not dispatch jira:issue_updated webhook to <WEBHOOK_URL>; a maximum of 500 dispatches are already in flight
2025-03-25 14:05:00,000+0000 webhook-dispatcher:thread-1 DEBUG anonymous     [c.a.w.internal.publish.DefaultWebhookDispatcher] Skipping webhook invocation [f63f8397-7328-48d8-9c22-2a4eb2e30954] to <WEBHOOK_URL> (Too many webhook dispatches already in flight)

Simplified:

Could not dispatch <EVENT_NAME> webhook ... a maximum of <MAX_IN_FLIGHT_DISPATCHES_COUNT> dispatches are already in flight
Too many webhook dispatches already in flight

Problem 3: failure exponential backoff

You observe the following error in your atlassian-jira.log file:

2025-03-25 14:05:00,000+0000 webhook-dispatcher:thread-1 WARN anonymous     [c.a.w.internal.history.DefaultInvocationHistoryService] Request to <WEBHOOK_URL> resulted in an error: Webhook failed too many times. Skipping this webhook for the next 11933ms

Simplified:

Webhook failed too many times. Skipping this webhook for the next <DELAY>ms

Solution

Tuning webhook event/JQL configuration

Have you considered adjusting your webhook configuration within Jira? Reducing webhook scope will decrease workload and avoid limits. Please consult Best practices on working with webhooks in Jira Data Center for recommendations.

These parameters differ from Jira 9, which used JVM arguments instead of application properties. Any webhook JVM arguments carried over from Jira 9 will not affect Jira 10.

The following parameters can be added to the jira-config.properties file (Advanced Jira application configuration).

Parameters for Problem 1

TitlePropertyDescriptionDefault Value

Queue size

webhooks.executor.queue.sizeThe size of the webhook processing queue. Any additional pending requests will be dropped and unrecoverable.250

Executor thread pool size

webhooks.executor.thread.countThe number of webhook-dispatcher worker threads. Additional threads may increase CPU usage but will improve queue throughput.5

Enqueue timeout

webhooks.executor.queue.wait.timeout.millis

How long (milliseconds) a webhook event-producing thread will wait to add to a full queue before timing out. Setting this value too high could force users to wait indefinitely for their HTTP request to return.100

Parameters for Problem 2

TitlePropertyDescriptionDefault Value

Max in-flight webhooks

webhooks.max.in.flight.dispatches

The maximum number of webhooks that can be dispatched concurrently. This includes webhook requests that are currently in transit over the network, as well as those waiting for HTTP connections.

Any additional requests will be dropped and unrecoverable.

Before increasing this limit, consider tuning the I/O thread pool size, max number of HTTP connections per host, and max HTTP connections.

500

Dispatch timeout

webhooks.dispatch.timeout.millis

How long (milliseconds) a webhook-dispatcher thread will wait to add to the dispatch queue when the max in-flight webhook limit is reached.

If unsuccessful, the webhook will be dropped.

250

HTTP connections per host

webhooks.max.http.connections.per.host

The maximum number of concurrent HTTP connections allowed per host for dispatching webhooks.5

Total HTTP connections

webhooks.max.http.connections

The maximum number of concurrent HTTP connections for dispatching webhooks.

A higher number of HTTP connections with insufficient I/O threads will increase the number of in-flight webhooks.

200

I/O thread pool size

webhooks.io.thread.count

The number of HTTP I/O threads. Additional threads may increase CPU usage but will improve queue throughput.

3

Parameters for Problem 3

TitlePropertyDescriptionDefault Value

Backoff trigger count

webhooks.backoff.trigger.count

The maximum number of consecutive failures before a webhook is deemed unhealthy and subsequently skipped.

A single successful dispatch will mark the webhook as healthy.

5

Backoff initial delay

webhooks.backoff.initial.delay.secondsHow long (seconds) an unhealthy webhook is skipped when first deemed unhealthy.10

Backoff exponent

webhooks.backoff.exponent

An unhealthy webhook is skipped with an initial delay.

If the webhook continues to fail, this duration will keep on increasing based on this delay exponent up to the max delay or until the webhook is healthy.

The backoff delay is computed as:

(initial backoff delay) * (backoff exponent ^ (number of failures - backoff trigger count))

up to the configured max delay.

1.2

Backoff max delay

webhooks.backoff.max.delay.hours

The maximum duration for which an unhealthy webhook is skipped.

2

Last modified on Apr 9, 2025

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.