Context: A system tracks some sort of transactions (e.g. money flow) for it's whole user base. At the end of the month each entity capable of receiving transactions has to be sent exactly one bill containing all the transaction's of the current month. This system is instanced, meaning that there are multiple instances (servers) of the system running.

How to handle this sort of scenario? I must not allow duplicate monthly transaction evaluations. Given the nature of the system a master-slave architecture is ruled out as master-election or master-slave in general is not scaling to a large amount of instances.

I would like to spread the load of the monthly transaction aggregation across all running instances. The transactions are stored in a database in the form (user_id, transaction_target_id, transaction_amount). Failed monthly transaction aggregations should be retried by another instance

In short: I need exactly-once guarantees for a distributed system without a master-slave concept


1 Answer 1


Exactly-once guarantees can be had the easiest with a (option 1) message queue system. This also neatly solves the problem of retries, as failed operations can be stuffed back into the queue, or a dead letter queue can be used.

You can technically run n agents on the problem (option 2), and each agent only processes users with ((int)userId) % n == agentId). Or a less naive partitioning algorithm. But you'll still have most of the issues present in a consensus algorithm.

You can use RAFT directly (option 3)

You can extend the database table with an "in processing by node id" column (option 4). The nodes can then claim rows and use the presence of their value as a precondition for further operations.

I'd probably run an upstream duplication checking algorithm so duplicates can be caught before they get sent to a customer.

  • Thanks for your answer! One last question: is it really necessary to have a leader/master node (like in RAFT)? Wouldn't this suffice: 1) select a transaction receiving entity which is not processed yet 2) lock it inserting the nodes id 3) reselect the entity with the condition that the current nodes id matches 4) if not, start again 5) release "timeouted" locks from time to time ? Of course this has to be done with the highest transaction level isolation (serializable). Do you know if this approach has a name?
    – roookeee
    Commented Feb 16, 2020 at 1:50
  • that's what I meant in option 4. Not sure if it has a name, it's a form of optimistic locking (because the agent proceeds to do the work and may discover later that it does not actually own the row)
    – Martin K
    Commented Feb 16, 2020 at 22:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.