mik284

mik284

Handling Race Conditions in an Event Ticketing System with Oban

I’m currently building an event ticketing system in Elixir and I’m looking for advice on properly handling race conditions around ticket inventory.

I’m using Oban for background processing with jobs responsible for:

  • Initiating payments

  • Delivering tickets after successful payment

  • Restoring tickets when payment fails or expires

The main inventory field being updated is rem_quantity.

I also have a cron job that periodically checks for pending orders older than 5 minutes and marks them as expired.

My concern is around concurrent updates to ticket inventory. For example:

  • Multiple users attempting to reserve the same ticket simultaneously

  • A payment succeeding while the expiration cron job is running

  • Ticket restoration jobs conflicting with payment confirmation jobs

At the moment, I’m worried this could lead to inconsistent rem_quantity values or overselling.

I’d appreciate guidance on best practices for handling this in Elixir/Postgres. Specifically:

  • Should I use database row locking (FOR UPDATE)?

  • Is optimistic locking enough for this use case?

  • What’s the recommended approach for inventory reservation in ticketing systems?

  • How should Oban jobs be structured to remain idempotent and avoid duplicate restoration/delivery operations?

Would also appreciate examples or patterns from production systems if anyone has implemented something similar.

Most Liked

LostKobrakai

LostKobrakai

Yes. Transactional guarantees are not enough for this usecase.

I’d suggest not having a rem_quantity in the first place. Instead create actual ticket records in the number of tickets you’ll want to sell. Update those. Number of sold or available tickets are an aggregation on those records. If that turns out a to hot a query for your system you can still cache their values on the read side e.g. with a materialized view, but do not use that on the write side / when checking for available tickets. All the actions like reserving, paying, freeing for tickets should happen in the context of a concrete ticket record.

If you have Oban involved or not at best doesn’t matter at all - at least to the database level modeling.

Last Post!

sarge

sarge

In general I agree with @LostKobrakai. I suggest you think about the process of securing a ticket, it would be claimed and then possibly purchased or the cart is abandoned and the ticket is returned to the pool. Each of these moments require you to consider an individual ticket instance. Some ticketing situations being oversold is a definite problem, assigned seating for example. You likely want to use optimistic locking as you move tickets through various states, but you need to expect to have to retry on occasion or error.

Where Next?

Popular in Questions Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31494 112
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement