I have a pre-configured Firebase Stripe extension that will handle the Stripe role responsible for allowing access to premium content. Additionally, I have my own webhook that will call an onRequest function to perform some data migration. The issue is, I want to catch the previous stripeRole before it is changed by the extension. Yet, I want to know if there is any order in which the stripeExtension and the Firebase onRequest cloud function are triggered by a webhook. Both the webhook and the cloud function will be triggered by the same event. is there is a priority for the extension over the on request ?

- 565,676
- 79
- 828
- 807

- 1,804
- 10
- 38
-
1Even if the messages are published sequentially and received by consumers in order there is no guarantee that either Cloud Function will be invoked successfully in any given sequence. The Cloud Functions contract is that you should expect a triggered function to be invoked *at-least-once* but it makes no guarantees about when or in what order. – anothermh Aug 17 '23 at 18:58
-
@anothermh This is exactly what I wanted to hear, so it is not reasonable to depend on the precedence. Please write an answer, as I think it could help someone, just as it helped me, so I need to set my logic to depend on solid data rather than data that can be effected by what the extension will do. – Richardson Aug 17 '23 at 19:21
2 Answers
Firebase Extensions are just prebuilt Cloud Functions here. They take no precedence over other Cloud Functions that run in your project.
If you want these actions to execute in a certain order, you will have to enforce that order in your application logic - for example:
by having your Cloud Function trigger/filter on the result of the Extension, like listening for its updates and inspecting the Firestore data or those - or
if the Extensions fires a custom event, to trigger on that.
A quick scan of the documentation shows that the Run Payments with Stripe extension:
This extension emits events, which allows you to listen to and run custom logic at different trigger points during the functioning of the extension. For example you can listen to events when a product has been added via the
product.created
event, or whenever a payment has succeeded through theinvoice.payment_succeeded
event.If those do not allow you to implement your use-case, consider filing a feature request (or better yet: a PR) for adding the required custom event here.

- 565,676
- 79
- 828
- 807
This answer will elaborate on the comment I left on the question.
There is no guaranteed order of execution. When you publish a request to invoke an event-driven function there's a series of steps that your request has to go through before your code in the function is actually invoked. Each step can introduce latency or have other issues that causes the functions to be invoked in any order.
Take a look at this workflow representing your function invoking two other event-driven functions foo and bar:
Keep in mind I've made up example latencies for the image and that the image is not a completely accurate picture of what happens, it's a rough approximation for the purpose of talking through the example.
The workflow shows requests to invoke the function. Each request is passed along a chain until it eventually runs your other functions.
Starting at the top we have your function that first requests that foo is triggered, then after making the request it requests that bar is triggered.
Let's look at the timeline, moving down the flowchart as we go:
- 0ms
- start
- 10ms
- foo request is published
- 20ms
- bar request is published
- 25ms
- bar request reaches the trigger
- 35ms
- bar request is processed by the control plane
- 40ms
- bar request reaches the Functions Framework
- 50ms
- foo request reaches the trigger (after some latency)
- Functions Framework invokes bar
- 60ms
- foo request is processed by the control plane
- bar finishes running
- 180ms
- foo request reaches the Functions Framework (after some latency)
- 190ms
- Functions Framework invokes foo
- 200ms
- foo finishes running
- end
So even though you may publish requests to trigger other functions sequentially it's possible (and normal) for them not to fire in-order. There are two main reasons why:
- There is high variability in how long any given step in the chain may take
- Imagine any kind of latency introduced, e.g., network latency, CPU utilization, cache availability, different CPU architectures, disk latency, memory latency, hardware or software crashes, magnetic storms, etc.
- Each step in the chain is completely isolated both from other steps and from other invocations of itself
The pattern employed here is the chain of responsibility pattern:
Like many other behavioral design patterns, the Chain of Responsibility relies on transforming particular behaviors into stand-alone objects called handlers. In our case, each check should be extracted to its own class with a single method that performs the check. The request, along with its data, is passed to this method as an argument.
The pattern suggests that you link these handlers into a chain. Each linked handler has a field for storing a reference to the next handler in the chain. In addition to processing a request, handlers pass the request further along the chain. The request travels along the chain until all handlers have had a chance to process it.
That means that none of the links in either chain know that two requests were published. The are only three things any link in either chain knows:
- What business logic to apply to this request
- Where to send this request after applying the business logic
- How to abort this request
This pattern underpins a lot of Pub/Sub applications and generally underpins how a lot of GCP services work. (which are themselves often reliant on Pub/Sub)
As Frank said in his answer, if you require sequential invocation then that has to be managed within your code because the event-driven architecture is asynchronous by nature.

- 9,815
- 3
- 33
- 52