Let's talk
engineering

Two payouts that look identical on a bank statement and must never share a table

Two rows leave the business every month and land in another company’s bank account. One is a partner’s share of profit on a site they co-invested in. The other is an agency’s commission for introducing a client. On a statement they are indistinguishable — a payment to a company, monthly, in the ordinary course of business.

They were nearly modelled as one thing. The requirements document I wrote had to carry a table explicitly headed “two commissions, do not confuse them”, because in the meeting where both were described the word commission was used for both.

What actually differs

Set them side by side and almost nothing lines up.

The partner’s share is a percentage of net profit on a specific project — revenue minus approved expenses, where expenses include the site’s rent or licence fee, operational costs and vendor payments. The percentage comes from a cap table: how much each partner put into the project. It is accounted monthly and paid within thirty days, and each partner realises it by raising their own invoice for their share, which means the payout is a purchase from the platform’s point of view, with tax on it.

The agency’s commission is a percentage of business introduced, not profit, and it is not tied to any project. It runs across the agency’s whole book. It is monthly, and there is additionally a year-end bonus on total annual volume, which is a second calculation on a different period with a different basis.

So: different basis, different denominator, different period, different scope, different settlement mechanism. The only shared attributes are “monthly”, “money out” and “to a company”. Two of those three are true of the electricity bill.

Where the merge would have hurt

If they share a table, the table needs a basis amount that means net profit for one kind of row and introduced revenue for another. It needs a rate that is an investment percentage in one case and a commission rate in the other. It needs a period that is a month for most rows and a financial year for some. And the moment someone writes a report of “total commissions paid”, they will sum rows whose denominators are not comparable and publish a figure that means nothing.

That last one is the real cost. Two things with the same shape and different meaning will eventually be added together by someone who only sees the shape. It might not be you and it will not be soon, which is exactly why the separation has to be in the schema rather than in a convention.

They ended up as two entities. Partner settlement carries a project, a party, a period key and a computed share, generated idempotently per month from the project’s own profit and loss. Agent commission carries a party, a type of monthly or year-end, a basis amount, a rate and an amount. Neither can be mistaken for the other by a report writer who has not read this document.

Where the merge was right

The same requirements pass took the opposite decision on the parties themselves, and the contrast is the useful part.

Client, agent, partner and supplier were four different words in every conversation and could easily have been four tables. They are one table with role flags. A client is a company with an address, a tax registration, bank details, a contact and a name — and so is an agent, and so is a supplier. More to the point, a single company genuinely holds more than one role: an agency that introduces business may also be a client on its own account.

Four tables would have meant four copies of that company’s address, four places to update its tax registration, and no way to answer “everything we do with this company” without a union of four queries.

So the rule that separates the two decisions is not about how similar the words are. It is: merge things that share an identity; separate things that share only a shape. A company is one identity playing several roles. A profit share and an introduction fee are two different calculations that happen to produce a similar-looking row.

The mistake I did make

I put a visible role selector on the party form — four checkboxes, choose what this company is. It was removed later because it made every user answer a question they should not have to. In practice the role is known from context: you are adding a client because you were on the client list when you clicked add.

The flags stayed on the record, so a company can still hold several roles and the model is unchanged. Only the selector went. That distinction is worth keeping: the data model should hold the general case and the interface should default to the specific one. Making the user express the model’s full generality on every create is not flexibility, it is an unanswered question in a form.

The limit I would state honestly: the year-end bonus is modelled as a row with a different type on the same commission entity, which is the one place I still expect trouble. It shares a table with the monthly rows and it has a different period basis, so it is precisely the situation this article warns about — inside the entity rather than across two of them. It has not caused a wrong total yet.

Working on something like this?

We build this kind of software, and we staff the teams that do.

Get in touch