Asynchronous Events
Architecture​
Asynchronous webhooks can be used for reacting to the events emitted by Saleor.
The worker instance will send the event payload via the chosen protocol. Your App or service should acknowledge receiving the payload, by responding with HTTP 200 status. If a successful response has not been received, for example in the case of temporary service unavailability, the worker instance will retry delivery. The delivery is triggered a maximum of five times. Behind the scenes, Saleor uses an exponential backoff strategy with the retry interval calculated as 10 * (2**retries) seconds.
The asynchronous events are meant to be used for Apps or services that do not require processing on the Saleor side. If you need to send data back to the user (for example, calculated shipping cost), you should use a synchronous webhook.
Examples of the use cases​
- Sending an order confirmation to the company chat.
- Synchronizing stocks with an external warehousing system.
- Updating Elasticsearch or Algolia indexes after changing product descriptions.
- Triggering frontend SSR for new pages.
Permissions​
Managing webhooks is available for users with the MANAGE_APPS permission. The App can also create and modify its own webhooks without the need for additional permissions.
Webhook protocols​
Asynchronous webhooks support the following protocols:
- HTTP(S)
- Google Cloud Pub/Sub
- AWS SQS
A protocol is chosen based on the targetUrl scheme.
HTTP(S)​
Webhook payloads are sent in POST requests.
All webhooks with targetUrl, where the scheme is HTTP(S) will use this protocol.
While HTTPS webhooks are a familiar concept and may seem easy to implement, ensure your endpoint can handle the same level of concurrency that you expect from the monitored events. Saleor Cloud will do its best to deliver webhooks in real-time, which could mean more traffic than your servers can handle. Because of this and the possibility of losing events when the destination server is down, we recommend using a queue like Google Cloud Pub/Sub or AWS SQS (see below).
Time limits​
Webhook endpoints must respond within 20 seconds, including the network latency.
If your application performs long-running operations, consider using a task queue instead.
Fault tolerance​
Event delivery will be retried up to 5 times with exponential backoff if:
- the endpoint cannot be reached
- the endpoint does not respond in time
- the endpoint responds with a transient HTTP error code (5xx)
Event delivery will not be reattempted if:
- the endpoint responds with an HTTP redirect (3xx)
- the endpoint responds with a non-transient HTTP error code (4xx)
Sending webhooks to Azure Service Bus​
You can use HTTP webhooks to deliver messages to Azure System Bus queues.
To do this, set the endpoint address to the HTTP endpoint of the Azure Service Bus queue or topic.
The structure of targetUrl should be as below:
https://<service-namespace>.servicebus.windows.net/<queue-or-topic>/messages
Then, add the following custom headers according to the Azure System Bus documentation:
AuthorizationBrokerProperties
Note that Content-Type cannot be specified as a custom header and will be filled by Saleor when sending the webhook.
Google Cloud Pub/Sub​
All webhooks with the gcpubsub scheme will be treated as the Google Cloud Pub/Sub webhooks.
The structure of the targetUrl scheme should be as below:
gcpubsub://cloud.google.com/projects/<your-project>/topics/<your-topic>
Authorization​
If you are a Saleor Cloud user, you need to add saleor-cloud-pubsub@saleor-cloud-286109.iam.gserviceaccount.com to the list of permitted publishers of the queue in question.
If you are self-hosting, you need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable.
AWS SQS​
All webhooks with the awssqs scheme will be treated as AWS SQS webhooks.
The structure of targetUrl should be as below:
awssqs://<access-key-id>:<secret-access-key>@sqs.<region>.amazonaws.com/<account-id>/<queue-name>
FIFO queues (ending in .fifo) must be configured to have ContentBasedDeduplication enabled.
MessageGroupID will be set to Saleor's domain name.
Payload Generation​
Saleor builds the payload of an asynchronous webhook in one of two ways:
- In the request. The payload is built as part of the API request or background job that triggered the event. It reflects the state of the object at that moment.
- Deferred. The request only records that the event happened. A background task on a Saleor worker builds the payload later, by resolving the subscription query against the state of the object at that time. The request finishes faster, but the payload reflects the state at generation time, not at the time of the request that triggered the event.
Deferred generation applies only to webhooks with a subscription query. Legacy webhooks without a query always build their payload in the request.
Deferred Events​
Payloads of CHECKOUT_CREATED and CHECKOUT_UPDATED are deferred from Saleor 3.21. Payloads of the following events are deferred from Saleor 3.23:
ORDER_CREATED,ORDER_CONFIRMED,ORDER_UPDATED,ORDER_CANCELLED,ORDER_EXPIRED,ORDER_FULFILLEDORDER_PAID,ORDER_FULLY_PAID,ORDER_REFUNDED,ORDER_FULLY_REFUNDEDORDER_METADATA_UPDATEDDRAFT_ORDER_CREATED,DRAFT_ORDER_UPDATEDFULFILLMENT_CANCELED,FULFILLMENT_METADATA_UPDATED,FULFILLMENT_TRACKING_NUMBER_UPDATEDPRODUCT_VARIANT_DISCOUNTED_PRICE_UPDATEDPRODUCT_VARIANT_OUT_OF_STOCK_IN_CHANNEL,PRODUCT_VARIANT_BACK_IN_STOCK_IN_CHANNEL,PRODUCT_VARIANT_OUT_OF_STOCK_FOR_CLICK_AND_COLLECT,PRODUCT_VARIANT_BACK_IN_STOCK_FOR_CLICK_AND_COLLECT
Saleor Cloud may defer payload generation for all events at any time, without a change of the API version.
What Deferred Generation Means for Your App​
When two changes to the same object happen close together, both deliveries can be generated after the second change and carry the same, newer state. For example, two orderMetadataUpdated deliveries can both contain the metadata written by the second mutation. Both deliveries are still sent, but you cannot use them to replay the sequence of changes.
Deferred deliveries keep the issuedAt and issuingPrincipal of the request that triggered the event. If the object is deleted before the task runs, the delivery fails.
Choosing Payload Generation per Webhook​
Added in Saleor 3.23.41.
Set payloadGeneration on the webhook to choose how its payload is built:
DEFERRED(default): the payload is built by a background task, as described above.IMMEDIATE: the payload is built in the request that triggered the event, the way all events worked before deferred generation was introduced.
The setting is available in webhookCreate, in webhookUpdate, on the Webhook type, and as payloadGeneration on each entry of the webhooks list in the app manifest. It has no effect on legacy webhooks, synchronous events, and events that are not deferred.
mutation {
webhookCreate(
input: {
name: "Order metadata sync"
targetUrl: "https://erp-sync.example.com/webhooks/order-metadata"
asyncEvents: [ORDER_METADATA_UPDATED]
payloadGeneration: IMMEDIATE
query: "subscription { event { ... on OrderMetadataUpdated { issuedAt order { id metadata { key value } } } } }"
}
) {
webhook {
id
payloadGeneration
}
errors {
field
code
}
}
}
A change of the setting applies to events triggered after the update. Deliveries created before the change finish the way they started, so around a change a newer delivery can be sent before an older one.
IMMEDIATE makes the request that triggers the event slower, because the payload is resolved before the request returns. Use it only on webhooks that need it.
The order in which deliveries arrive is not guaranteed in either mode. If you need to apply changes in order, include a field such as issuedAt in your subscription query and discard deliveries older than the last one you applied.
Available webhook events​
The WebhookEventTypeAsyncEnum represents the latest list of asynchronous webhooks