Referral structures
How referrals are recorded, how direct, binary and unilevel differ, why binary placement does not decide who gets paid, and what approval, spillover and structure changes do to an existing network.
Everything the programme pays is decided by two things: the referral record that says who introduced whom, and the structure that says how far up that chain a commission travels. The tree diagrams your members look at are a third thing, and they are not involved in the arithmetic at all.
The referral record
One row in mlm_referral per relationship: a referrerId, a referredId and a
status of PENDING, ACTIVE or REJECTED.
It is created in exactly two ways.
By registration. A visitor arrives at /register?ref=<user id> and signs
up. Both the email/password and the Google sign-up paths honour it. Note the
parameter: it is the referrer's user UUID, not a short code, not a username.
There is no separate referral-code table — the member's own id is the code, and
the link generator simply pastes it into a URL.
By an administrator, on Admin → Affiliate → Referrals, by picking a referrer and a referred user.
Two rules are enforced at creation, and both fail closed:
- No self-referral. Registering with your own id as
refis ignored, and the admin create route rejects referrer and referred being the same person. - One sponsor, permanently.
referredIdcarries a unique index. A user can appear as referred exactly once, ever. There is no re-assignment, no "transfer to another sponsor", and a soft-deleted referral still occupies the slot.
When BINARY or UNILEVEL is active, a member who has no referral record of
their own gets a self-referral row written for them (referrerId =
referredId) the first time they need a tree root — when someone signs up under
them, or when they open the Network page.
That row consumes their unique referredId slot. If you later want to record
that this member was themselves introduced by somebody, you cannot: the insert
violates the unique index. Decide your top-level sponsors before you turn on a
multi-level structure.
Approval
Admin → Affiliate → Settings → Require Approval decides whether a new
referral starts ACTIVE or PENDING.
A PENDING referral is not a member of anything. It earns no commission — both
reward engines only consider ACTIVE rows — and it is deliberately not placed
in the tree. Placement happens at the moment of approval instead.
That matters most under BINARY, where each node has only two child slots. If
pending referrals were placed immediately, an application you were never going
to approve would occupy a slot and push a genuine member into spillover
somewhere else in the tree.
Rejecting works the other way round: the node is detached from its parent, the parent's freed child slot is cleared, and any children the rejected node had are re-parented to its parent so a rejection cannot orphan a live sub-tree.
The three structures
Set on Admin → Affiliate → Settings. One setting, platform-wide, applied to every future transaction.
DIRECT
The default. There is no tree and no node table. A commission goes to the immediate sponsor at the condition's full rate, and stops there.
If you are running a straightforward "refer a friend, earn 2% of their deposits" programme, this is what you want. It has no configuration beyond the conditions themselves and nothing about it can be misconfigured into paying nothing.
UNILEVEL
Every referral gets a node in mlm_unilevel_node whose parent is the sponsor's
node. A sponsor may have any number of direct children.
A commission is split across 2–7 levels of sponsors by percentage. With levels set to 3 and shares of 50 / 30 / 20, a 2% deposit commission on a 1,000 USDT deposit produces 20 USDT of commission, distributed as 10 / 6 / 4 USDT to the member's sponsor, their sponsor's sponsor and so on.
BINARY
Every referral gets a node in mlm_binary_node, which holds a parent and
exactly two children — left and right.
Placement is under the sponsor's node. If both of the sponsor's slots are already full, the system searches breadth-first from that node for the nearest free slot and places the new member there. That is spillover: a member you introduced appears underneath one of your existing downline rather than directly beneath you.
The tree is also cycle-checked before placement. If the person being placed is already an ancestor of the target node the request is refused with a 409 rather than creating a loop.
The thing that surprises everyone
Both BINARY and UNILEVEL resolve their payees by walking
mlm_referral.referrerId — the sponsor chain, who invited whom. Neither
consults mlm_binary_node when paying.
So "Level 1 … Level N" on the settings screen means levels of the sponsor chain, not depths of the binary tree, and a member placed by spillover is still paid through the person who invited them, not through their tree parent.
Binary placement, the two-child limit and the spillover diagram are presentation. If you are costing a binary compensation plan on the assumption that spillover changes payout paths, the numbers will not match what the platform does.
The consequence is blunt: BINARY and UNILEVEL pay identically for the same
level percentages. Choosing binary changes what members see on the Network
page and how the structure feels; it does not change anyone's earnings. Choose
it for presentation, not economics.
How the upline walk actually runs
Starting from the member who transacted, the engine repeatedly asks "who referred this user?" and collects up to N sponsors, where N is your configured level count. It stops early on any of:
- No referral record — the top of a chain. Normal, not an error.
- A self-referral (
referrerId=referredId). This marks the top of the tree. Without that stop, the person at the top would be paid at level 2, then again at level 3, 4 and so on for a single transaction. - A cycle — a sponsor already seen during this walk. Hand-edited or imported referral tables can contain them; the walk stops and logs a warning rather than looping.
Every level found is paid its configured share. Levels with nobody in them are simply not paid — the money is not redistributed to the levels above.
Level percentages
Between 2 and 7 levels, each with a percentage. Two hard rules:
- A level with no configured percentage is skipped, not defaulted. If you set the level count to 5 but only fill in three boxes, levels 4 and 5 earn nothing.
- The total must be 100% or less. Above that the engine logs an error and returns without creating a single reward — not just for the excess level, for the whole transaction. The settings screen shows a running total and turns it red for this reason.
The percentages are shares of the commission the condition produced, not additions to it. Setting all levels to 100% each does not multiply your payout by the number of levels; it stops payouts entirely.
Changing structure on a live programme
The structure setting is read at the moment a commission is calculated and at the moment a referral is placed. It is not a migration.
Switching from DIRECT to BINARY or UNILEVEL starts creating nodes for
new referrals only. Historical referrals have no node, so they do not appear
in the tree diagram — but they are still paid, because payouts walk the referral
table rather than the nodes. Members will ask why their existing downline is
missing from the Network page.
Switching between BINARY and UNILEVEL leaves the old node table
populated and starts filling the other one. Nothing migrates. Payouts are
unaffected, because neither table is consulted for payment.
Switching back to DIRECT stops multi-level payouts immediately — only the
immediate sponsor earns from the next transaction onward. Existing unclaimed
rewards keep their amounts; they were already calculated.
A reward row stores a settled amount. Changing the structure, the level percentages or a condition's rate changes what future activity earns and nothing about what has already been credited. There is no recalculation job and no back-dating.
What members see
The Network page renders the structure that is currently configured: a flat list
of direct referrals under DIRECT, the sponsor hierarchy under UNILEVEL, and
the binary node tree under BINARY. Depth is capped at your configured level
count, and under BINARY at 10 regardless, so a deep tree renders as a
manageable slice rather than trying to load everything.
If the structure is set to BINARY or UNILEVEL but no level count is
configured, the page returns an empty structure containing only the member
themselves — a valid response that looks like a bug. Set the levels.
Next: Commission conditions for the rules that decide what a transaction is worth in the first place.