(Copied from Joseph’s notion)
High Level Observations
This section isn’t necessarily good or bad, just things that I thought we interesting to call out and will be referencing in the next section. I’ve primarily focused on the betting flow, but I think most of this doc applies across the codebase.
- Business plans
- The business only uses play currency now
- The business wants to start real money payouts
- Problem domain
- The workload in this domain is Embarrassingly Parallelizable™
- https://en.wikipedia.org/wiki/Embarrassingly_parallel
- Market places lend themselves well to queues and batch processing
- There has been a colossal amount of money and thought dumped into this problem
- Coding practices
- Asynchronous processing is not being used
- There is no formally verifiable source of truth regarding balances
- More on this below…
- There does not appear to be scheduled downtime
- Database usage
- The team isn’t using an ORM, but has mostly built one from scratch
- i.e.
updateData()
- Not many advanced features being used
- I have a feeling this stems from the initial stint in Firebase, which is NoSQL
- There are a lot of database functions and triggers
- There is very little usage of foreign keys
- Also think this stems from Firebase
- There doesn’t appear to be a real migration plan for database changes
Priorities
Given what’s written above, I think there are a few “classes” of concerns here.
- Correctness
- Is every deposit accounted for?
- Is every bet accounted for?
- Could someone ask for the state of an arbitrary market at an arbitrary point in the past?
- Could someone ask for the state of an arbitrary user at an arbitrary point in the past?
- Reliability
- If the user balances were wiped, could you recover them?
- Are there exercised disaster recovery procedures?
- What is the failure mode when load goes up?
- Performance
- How many concurrent users can be on the site?
- As load increases, will the markets always reflect reality?
Proposals
Migrate the data model towards an append-only ledger
From a correctness and reliability point of view, this is a worrying gap in the system architecture. While there are potential performance penalties for a naïve implementation, this will enable you to sleep at night when the site burns down during a crazy news day.
A centralized ledger allows you to have a single, rewindable source of truth regarding the entire financial state of your system. Given any user or any contract, you can just start at the beginning of the ledger and sum every relevant entry up to whatever date you’re interested in. There is literally a whole profession based around this (Accounting) as well as text books on their implementations. For an initial proposal, it’s hard to write more without getting into the weeds.
The primary tradeoff here is performance. As you may have surmised, having a centralized ledger effectively turns the transactions table into a linked list with a single head pointer. However you can…
[J] See also this user’s creation of a ledger with Manifold in mind:
https://github.com/syvb/yosoku-core/blob/master/README.md