Event Monitoring / 4 min read
Sync vs Async Event Ingestion for Fraud Decisions
Call sync when the product cannot continue without ALLOW, REVIEW, or BLOCK. Queue the event when operations can look after the fact.
By Naiza
27 Jun 2026 · Updated 5 Oct 2026
Most fraud stacks need both paths. Sync is for the moment the product has to decide before it continues. Async is for the event you still want evaluated, enriched, or reviewed without making the customer wait. Teams get into trouble when they pick one mode for the whole app, then spend a quarter adding the other mode under an incident.
The question I ask in the design review is not “which API is newer.” It is “can this user keep going if we do not have an answer yet.” If the answer is no, you are on a sync path. If the answer is yes, you can queue.
Sync when the action has to wait
Use POST /api/v1/events when the next product state depends on ALLOW, REVIEW, or BLOCK. That is the sync Events API. It returns the same uppercase outcomes as the rest of this post. Do not branch those values on POST /api/v1/decisions/evaluate: that surface maps them to lowercase approve, deny, and review. Payments, withdrawals, password resets, and high-risk profile changes belong on the sync event. So does anything that moves money or hands out a new session after a suspicious challenge.
POST /api/v1/eventsApply the decision in the same request thread. ALLOW continues. BLOCK stops the action and shows a state you have already written copy for. REVIEW adds friction or holds fulfillment and opens a case. If you ignore the decision and “decide later,” you did not need sync. You needed async plus a webhook, and you paid for a timeout in the checkout.
Persist the event id or decision id on the payment, login, or profile record. Support will ask why a transfer is pending. Engineering will ask which rule fired. Those conversations die if the id lives only in an ephemeral log.
Timeouts on a sync call are a product problem. Fail closed on money movement if you cannot get a decision and your policy says so. Fail open on a low-risk read if holding it is worse than a late review. Write that choice down per event name. Do not let each service invent its own fallback.
Async when waiting would be theater
Use POST /api/v1/events/async when the customer can finish and operations can look afterwards. Low-risk logins, portfolio monitoring, analytics enrichment, and streams that only need a case if something looks wrong are the usual set.
POST /api/v1/events/asyncYou get a job id and a later result, often through a webhook. That is why retries and idempotency matter more on this path. The webhook retries post is the operational half of async ingest. If you queue the event and then create a new case on every delivery, async will look cheaper in latency and more expensive in the queue.
Do not use async for a withdrawal just because the batch endpoint is easier to retry. The customer already thinks the money is moving. A BLOCK that arrives two minutes later is a reconciliation project. If the action changes balances or access, start with sync.
How I choose, event by event
If the customer cannot continue without the answer, sync. If operations can review after the fact, async. If traffic arrives in bursts and you only need a decision on a subset, async plus webhooks. If the action moves money or changes account access, sync first, then add async shadows for the events you want extra context on.
One customer journey can use both modes with distinct event names: a synchronous payment attempt and an asynchronous login event. Device-history rules can use the login context while checkout waits only for its own decision. Persist the event identifiers and define how related events join the case.
Shadow a new sync rule before you enforce BLOCK. The ingest mode and the rollout posture are different knobs. You can call POST /api/v1/events on every payment and still map BLOCK to REVIEW in your product until the false-positive rate is something the queue can defend. Naiza returns the decision. Your flag decides whether the customer feels it.
The event monitoring guide lists the request fields. Document each event name, ingestion mode, product response to REVIEW, and stored event identifier.
The customer should wait only when waiting changes an outcome they can see. Everything else can land in the queue. That is the whole distinction. The rest is which URL you call.