Skip to content
Back to blog
Architecture June 11, 2026 · By MEXAR Engineering

Event-driven by design: the queue pipeline under MEXAR

How MEXAR keeps transactions fast and side-effects reliable — events broadcast state changes, idempotent listeners run on queue workers, and webhooks are deduplicated end to end.

A money transaction does a lot more than move a balance. It notifies people, updates commissions and dashboards, and runs compliance screening. If all of that happened inline, every transaction would be as slow as its slowest side-effect — and a single failing step could take the whole operation down with it. MEXAR avoids that by being event-driven: the command that changes state is separate from the things that react to it.

Events broadcast, listeners react

When something significant happens, MEXAR raises a domain event, and independent listeners pick it up. The command handler does not know or care who is listening, which keeps notifications, statistics, and compliance decoupled from the core flow.

EventListeners react with
TransactionCreatedstakeholder notification, initial stats/commission calculation, AML screening
TransactionPaymentConfirmedpayment task processing, confirmation notification, dashboard refresh
TransactionRefundedrefund notification, seller-commission invalidation, dashboard refresh
DepartmentCurrencyRateChangedrate-changed notification, dashboard refresh

Adding a new reaction — say, a new analytics sink — means adding a listener, not editing the transaction code. The blast radius of a change stays small.

Listeners are idempotent and queue-backed

Critical listeners implement ShouldQueue, so they run asynchronously on the queue workers (RabbitMQ) rather than blocking the request. That makes the API fast, but it also means a job can be retried after a transient failure — and a retry must never double-apply its effect.

So the rule across the system is that anything that mutates data or dispatches jobs is idempotent and safe to run again. Where ordering or concurrency matters, listeners take a row-level lock instead of hoping for the best. Payout creation on payment confirmation, for example, locks the transaction first:

$transaction = Transaction::lockForUpdate()->find($transactionId);

Two confirmations racing for the same transaction serialize behind the lock; one wins and the other sees the already-updated state. DB transaction boundaries live in the listener that orchestrates the work, while the business logic itself sits in dedicated service classes — thin orchestrator, testable core.

Webhooks: receive fast, process once

External providers call back over webhooks, and the network will happily deliver the same callback twice. MEXAR separates receiving from processing: the controller stores the raw payload, returns 200 immediately, and hands off to a queued listener. Before that listener does any work, it checks for a duplicate using a content digest over a recent time window:

$exists = WebhookCallbackRawData::where('digest', $raw->digest)
    ->whereNotNull('processed_at')
    ->where('created_at', '>=', now()->subDays($windowDays))
    ->exists();

if ($exists) {
    return; // already processed — skip
}

A redelivered payload hashes to the same digest, is recognised, and is skipped — so a provider’s retry never books a transaction twice.

Tracing across the hops

Because work fans out across events and queue jobs, MEXAR threads a correlation id (for webhook-originated work, webhook-{raw_data_id}) through the whole chain — controller, listener, router, parser, and the events they emit. Every log line along the path carries it, so a single transaction’s journey across services can be reconstructed from end to end.

The payoff

None of this is visible to an end customer, and that is the point. The queue-driven, event-based design buys operators three things that matter at scale:

  • Speed under load — side-effects run off the request path, so spikes don’t slow confirmations.
  • Reliability — idempotent, retry-safe listeners and row-level locks mean a hiccup is recoverable, not corrupting.
  • Extensibility — new reactions attach as listeners, without touching the transaction core.

It is the same contract-driven thinking that lets MEXAR swap providers without a rebuild, applied to time instead of vendors: decouple what reacts from what acts, and the system stays fast, safe, and easy to extend.