KAZENAKAZENA
All posts

Withholding is not a tax on the payment; it is a tax on the year

August 24, 2026 · Taro — Founder, KAZENA

Withholding is not a tax on the payment. It is an instalment, paid partway through, against the tax owed for the calendar year. I thought I understood that, but our code was not written that way. It treated each payment as a calculation complete in itself. The result is that when the same person is paid twice, the second withholding comes out short.

V found it. She is the accountant in Jakarta who tests KAZENA Books with her own real data, and she has now built documents against the actual Coretax more than 20 times, sending back every place where they failed. What arrived was a single line: the withholding on the second payment is exactly the same as on the first.

Here are the numbers. A fee to an individual who is not an employee: 150,000,000 rupiah to the same person twice, in February and in August. For this category the taxable base is half of the gross, so 75,000,000 rupiah each time. The rates are the Pasal 17 progressive brackets — 5% up to 60,000,000 rupiah, then 15% up to 250,000,000.

The correct calculation is cumulative. The first payment is the tax on a cumulative base of 75,000,000 rupiah, which is 5,250,000 rupiah. The second is the tax on a cumulative base of 150,000,000 rupiah — 16,500,000 rupiah — minus the 5,250,000 already withheld, leaving 11,250,000 rupiah. Our software produced 5,250,000 rupiah for the second payment as well. The gap is 6,000,000 rupiah.

What happens is that the 5% band gets used twice. A person has one 60,000,000 rupiah band per calendar year. Calculate each payment in isolation and the lowest band is handed out once for every payment. The more payments there are, the larger the shortfall.

Who pays the difference. Withholding is the payer's obligation, so a shortfall is settled later by the payer, with penalties on top. The recipient did take home more, but asking for that difference back months afterwards is, in practice, close to impossible. So this was not a display discrepancy. It was a bug that costs money.

Why did it pass our tests. In our test data, each person had exactly one payment. Adding more people is easier than adding more history, so we built the data as one payment per person. Paying the same person twice — an entirely ordinary thing in real work — had never once appeared in it.

At the root was a mistaken unit of calculation. We were treating the payment as the unit. The unit the law looks at is the person across the calendar year. When those two disagree, every number looks right for as long as you are looking at a single payment. Correct on its own, wrong in aggregate — the hardest shape to catch.

Fixing it raised the next question: which date decides whether something falls inside the year. Not the date it was recorded, but the date it was paid. And whose clock decides when the date turns over. Read from the server's time, a payment made on the morning of 1 January in Jakarta lands on 31 December of the previous year. One payment crossing the year moves the starting point of the whole cumulative total. That now resolves in each country's local time.

We also had to decide what happens to documents already issued. Recalculating cumulatively can leave a withholding slip issued earlier disagreeing with the new figures. Silently rewriting them seemed to me the one thing we must never do. What we show now is the total already withheld, the total that should have been withheld, and the difference between them, side by side. Deciding how to correct it is a person's job, not the software's.

There is also a limit on our cumulative total: it is cumulative over payments recorded in KAZENA and nothing else. If the same person is also paid by other companies, the true annual total is larger. When software says nothing, people read the figure on the screen as the whole of it. We now print, beside that figure, one line saying what it does not include.

The screen changed too. It used to show only the net amount after withholding. It now shows, in order, the taxable base for this payment, the cumulative base so far this year, the tax on that cumulative base, the amount already withheld, and the amount being withheld now. It is a busier screen than before, but a number V cannot check is a number we cannot check either.

Let me say plainly that I am not a tax accountant. The rates and categories described here are our understanding as far as we have implemented them, and the final judgement belongs with a professional you consult. All we can do is make every step of the arithmetic visible. If your own software gives you the same withholding amount on a second payment to the same person as it did on the first, it is worth checking that one by hand.

Tell us what you think

How the KAZENA apps feel to use, what we should fix, features you wish existed — if you run a small or medium business or work freelance in Indonesia or the Philippines, your voice is exactly what we want to hear. Messages in Bahasa Indonesia or English are answered by teammates who know your market from the inside. KAZENA Books is already set to launch in the Philippines and Indonesia — and if your company would like to bring it to other countries as a partner, or is interested in acquiring the system, we would love to hear from you too. We also take on new system development. We are a small team, so we cannot always start right away — but what we build carries made-in-Japan quality and stays close to how business really works here, one project at a time.

Get in touch

More from the blog