- iGaming architecture
- domain design
- platform modularity
- data ownership
Modular iGaming Architecture: Who Owns the Rule, Record and Recovery?

Design useful boundaries between player accounts, wallets, games, payments and bonuses. Follow a mixed-funded stake through a late reversal and test the contracts between modules.
A bonus module marks a promotion as finished. Later, a game provider reverses a stake that used that promotion. The wallet still knows the amount, but not necessarily which funds may be restored, whether the bonus allocation remains usable or who is allowed to decide. If each module repairs its own view independently, an apparently tidy architecture can produce contradictory financial records.
Modularity is useful when it makes those decisions explicit. A boundary should identify the rule a component owns, the record it can change and the recovery it must support. This article proposes a practical responsibility map for an iGaming platform and tests it against a late reversal. The map is a starting point for discussion, not a universal list of services to deploy.
A domain boundary separates meanings and decisions
The same word can mean different things in different parts of a platform. An account module may describe a player’s identity and restrictions. A wallet may use a scoped account reference without needing the player’s documents. A game module needs a session and the rules for submitting operations. Combining these views into one editable player object makes unrelated changes depend on the same model.
Martin Fowler’s explanation of bounded contexts separates internally consistent models and makes their relationships explicit. In practice, define the vocabulary and permitted decisions within a boundary, then specify how another boundary refers to them. A common identifier can connect models without giving every component ownership of every field.
Do not equate a domain with a server. A domain is the area of business behavior being modeled; a bounded context states where a particular model applies. A module is an implementation boundary, and a service is a deployment choice. These can align, but deciding them independently avoids creating a new network dependency for every noun in the product roadmap.
For the wider decision process, use platform architecture services; for product coverage, use platform capabilities. Here, the narrower question is which component may change each important fact.
Write an ownership contract for each core capability
Describe each capability with its owned state, permitted commands, published facts and failure responsibility. The following list is a proposed decomposition; real provider contracts and product rules may require combining or splitting parts.
- Player accounts: own identity links, lifecycle and the restriction decisions assigned to this context. Expose the permission needed for a specific action rather than one generic active flag. A gameplay restriction and the settlement of an already accepted operation are different decisions.
- Wallet and ledger: own financial postings, reservations, currency and the source allocations required to explain them. Accept explicit reserve, consume, release or adjustment commands; reject invalid transitions. Other modules request financial changes through this contract rather than editing balances.
- Games and betting: own provider mappings, sessions, rounds or bets, and their lifecycle. Keep the original operation and financial references. If a sportsbook has distinct placement and settlement rules, describe that model separately rather than forcing it into a casino round model.
- Payments: own provider payment references and the deposit or payout workflow. A provider status and a wallet posting are related records, not the same fact. Keep an accepted but unfinished payout visible even when the payment provider is unavailable.
- Bonuses: own the promotion terms and versions, eligibility, progress and the rules assigned to the bonus context. Specify how those rules constrain wallet allocation and later restoration. Avoid having both bonus and wallet components independently decrement the same spendable amount.
- Back office and support: own cases, permitted staff actions and review history. Read across domains to explain an operation; submit an authorized command to its owner to change it. A convenient support screen is not permission to bypass the domain contract.
Within the financial model, identify an aggregate: the group of state that must remain valid through a change. Microsoft’s domain validation guidance places invariant enforcement inside that model. For this design, make the reservation transition, its financial effect and its duplicate handling consistent within the chosen transaction boundary. This does not mean treating the whole player journey as one giant database transaction.
For every responsibility, name both the code boundary and the team that can change its rules. If three teams can write the same financial field, a diagram naming one owner has not established ownership.
Distinguish a request to act from a fact that happened
A command asks an owner to perform an action; an event describes a committed fact. In an illustrative contract, ReserveStake requests a financial decision. StakeReserved records that decision. A reporting consumer can react later, but an event should not quietly become a second authorization to deduct the stake.
The distinction concerns semantics, not transport. A command can travel through a durable queue and complete later; a synchronous API can return the result of an already completed operation. State clearly whether a response means received, accepted or completed, and where the caller obtains the final outcome.
A useful cross-module contract includes:
- Scope and identity: operator, player or account scope, currency, stable operation reference and links to the original business action.
- Decision inputs: amount, allocation, relevant policy version and required current permissions. Specify which inputs are trusted and which the owner must verify.
- Outcome: allowed transitions, rejection reasons and the representation of an unresolved result. A timeout cannot be interpreted as proof that nothing happened.
- Repetition and order: the identity of the business effect, permitted retries, duplicate response and the rule for a later correction. The ordering key and version belong to the affected entity, not an assumed global event stream.
- Recovery: how accepted work is stored, inspected, resumed and reconciled, with a responsible team for exceptions.
Microsoft’s publisher-subscriber guidance highlights that delivery and ordering guarantees depend on the messaging system. State the guarantee used by this contract. Design the business operation to tolerate the duplicates or delays it permits; do not infer an exactly-once financial result from a broker feature.
Publish only the fields a consumer needs, with explicit schema versions. A shared event containing the entire internal player model creates a coupling and sensitive-data burden that a module boundary was meant to reduce. If a consumer needs a current decision, give it an appropriate decision contract rather than telling it to reconstruct authority from an old event.
Follow a mixed-funded stake through a late reversal
Consider an illustrative €5 stake funded by €2 cash and €3 bonus funds. The product supports mixed funding. Later, the provider sends a valid full reversal after the promotion has closed. Whether the bonus portion is restored, remains restricted or needs review depends on the approved terms and their applicability; architecture must preserve the evidence needed to apply that policy.
Walk the operation through its owners:
- Before acceptance: the game or bet workflow obtains the required player permission and funding decision. The contract explains where the permission is enforced relative to financial commitment, including what happens if a restriction changes during the operation.
- Reservation: the wallet records the original operation, currency, amount and funding allocation under the agreed rules. The promotion version or other decision reference must be sufficient to explain why that allocation was permitted.
- Game result: the game context associates the provider result with the original operation and asks the wallet for the permitted financial transition. Provider evidence does not independently edit wallet storage.
- Late reversal: the game context verifies the reversal’s relation to the original operation. The workflow obtains the applicable restoration decision and sends an explicit linked command to the wallet. The amount must be checked against the original effect and earlier corrections; a new provider message identifier does not authorize restoring the same funds again. The workflow does not rebuild the allocation from today’s aggregate balance.
- Resolution: the wallet commits the resulting transition and duplicate decision together under the business identity, or the workflow keeps the exception visible for authorized review. Support can explain the original allocation, applicable policy and current outcome from linked records.
Changing the player’s cash balance by €5 because that is the easiest field to update can silently turn bonus funds into cash. Restoring €3 to an arbitrary current promotion can be equally wrong. The original split is necessary evidence; it is not, by itself, permission to override the terms that apply to a reversal.
The useful design artifact is therefore a decision trail: original funding, relevant rule version, provider operation, requested correction, financial result and exception owner. Test the policy variants the product actually supports, including repeat reversal delivery and a promotion that is no longer available. Do not invent one global refund rule to make the implementation convenient.
Give incomplete work an owner across module boundaries
A cross-domain workflow needs durable progress even when its components are individually healthy. Track the business operation, completed steps, unresolved decisions and the next permitted action. An orchestrator can make this responsibility explicit; event-driven coordination can also work if ownership and progress remain inspectable. Avoid a design in which every subscriber assumes someone else will finish the operation.
For the reversal example, a healthy game adapter and a healthy wallet do not prove that the restoration decision reached the wallet. Make the incomplete handoff discoverable. If the financial result is unknown, retrieve or reconcile it before issuing a replacement command. Repetition of the same identified operation and creation of a new financial adjustment are different actions.
Use a specific exception state and owner. The case should show the original references, known facts, missing decision and approved recovery actions. A dead-letter queue is storage, not a completed support process. Reprocessing must preserve business identity and current authorization; it must not blindly repeat an expired decision.
When staff intervene, OWASP’s object authorization guidance calls for permission checks on the requested action and object. Apply the agreed operator scope to the underlying command as well as the screen. Link an authorized correction to its case and reason, and use the product’s approval requirements. A support user should not repair the system by writing directly into several modules’ tables.
Reconcile records that represent different parts of the operation: the provider reversal, game state, original allocation and wallet transition. A total that happens to match can conceal a missing operation and an unrelated extra one. Investigate by stable business references and currency, retaining unexplained differences instead of rewriting history to make the report look clean.
Enforce modularity before changing deployment topology
Enforce the ownership map in implementation. Give each module an explicit public interface, keep its internal records private and restrict direct writes to its owner. In a modular monolith, this can mean dependency rules, controlled persistence access and checks that prevent another module importing internal classes. Sharing one database does not require sharing unrestricted write access.
Keep domain types out of a growing common library unless their meaning really is shared. Currency representation or a technical identifier may be common; one universal Player object with verification, bonus progress and wallet internals usually makes changes travel across unrelated modules. Prefer explicit contract types and mappings at boundaries.
Inspect the dependency direction. If wallet logic must call the game module, which calls bonuses, which calls wallet again to complete a debit, the cycle deserves review. Move workflow coordination to an explicit application layer where appropriate, while leaving local rule enforcement with the state owner. Hiding the cycle behind network APIs adds failures without resolving the model.
Only then consider a separate deployment. Ask whether the boundary is stable, whether release or capacity independence has a concrete benefit, and whether a team can own its contracts and recovery. If most changes still require simultaneous releases and shared table edits, the proposed service is not operationally independent.
Test boundaries as well as individual modules: rejected cross-module writes, contract compatibility, concurrent repetition, late corrections, delayed read models and staff commands in another operator’s scope. Record which conditions were exercised. Passing a unit test for each module does not demonstrate that the complete financial workflow remains valid.
Review the boundaries through decisions the team must make
Review one real workflow with product, engineering, finance operations and support. For each important record, ask who defines its meaning, who can change it, which transition is permitted and who resolves an incomplete change. Turn unresolved answers into decisions with an owner and the evidence needed to close them.
The boundary is useful when a new rule can be assigned to the right owner, a disputed operation can be explained without manual joins across unexplained tables, and a failure can be recovered without competing financial writers. The goal is not the maximum number of modules. It is a model that preserves the product’s rules as the platform changes.
For deeper financial modeling, continue with wallet and transaction ledger design. To decide whether a boundary should become a network service, compare a modular monolith with microservices. Those are related decisions, but they should not replace defining the responsibilities first.
Use the core-module journey to review the broader flow and player account architecture to examine permissions and account state. If the obstacle is who can decide and own these changes, the fractional CTO discussion addresses technical leadership. Bring the resulting questions back to the responsibility map rather than expanding the diagram without a decision.
- For every critical fact, record its meaning, rule owner, permitted writer and public contract; identify consumers that hold only a copy.
- For a mixed-funded operation, preserve the original allocation and applicable policy evidence through settlement and later correction.
- Specify command completion, event delivery, repetition and ordering; keep unresolved work visible with an assigned recovery owner.
- Prove that implementation respects the boundaries, including support commands, cross-operator access and direct financial writes.
Does every domain need a separate service and database?
No. First define the model, authority and public contract. Modules can remain in one application if ownership is enforced. Separate deployment is useful when independent change, capacity or isolation has a concrete benefit and a team can operate the resulting failure paths. A database shared without unrestricted cross-module writes is different from shared ownership of every table.
Can modules share a player identifier?
Yes, with explicit scope and mappings. A shared reference can connect account, wallet and game records without requiring one editable player object. Define who issues the identifier, where it is unique and how merged or replaced references are handled. Each module still owns the meaning and permitted changes of its own records.
Are events safer than synchronous calls?
They solve different coordination problems. Events can decouple reactions to committed facts, but require clear delivery, order and recovery contracts. A command can also be asynchronous. Choose transport according to the decision and its completion requirements; do not authorize current financial activity solely from an old event or interpret a timeout as a confirmed rejection.
Who decides what happens to bonus funds after a reversal?
The product team must assign authority for the applicable restoration rule and have the approved terms interpreted by the appropriate operator and advisers. Architecture preserves original allocation, policy evidence and linked financial transitions so that decision can be applied and explained. Neither the game adapter nor a support screen should invent a rule because it is easier to update a cash balance.
Share a sanitized workflow, the modules that can change its records and one failure or correction the team cannot explain confidently. Discuss an architecture review with SPINDO.TECH focused on ownership, contracts and recovery evidence before committing to a new service split.



