A Moeda Não Existe De Forma Importante - Não é rara, mas vale muito: moeda de R$ 1 pode custar até 179.900% a mais
Não é rara, mas vale muito: moeda de R$ 1 pode custar até 179.900% a mais

So you need to handle currency and nobody can agree what it actually is

I spent three years running payment infrastructure for a Southeast Asian fintech where we processed transactions across six currencies simultaneously. The problem isn't coding the integration. The problem is that every backend system treats "money" differently, and these differences compound in ways that will absolutely destroy your margins if you don't catch them early. When I first started, I assumed currency was just a number with a label. EUR, USD, BRL. You store the number, you display the label, you move on. That assumption cost me approximately forty thousand dollars in a single quarter because of exchange rate timing mismatches between when a transaction was initiated and when it actually settled.

O conceito de a moeda não existe de forma importante

Here is the uncomfortable truth that most people in this space don't want to talk about: currency is not a fundamental thing. It is an accounting convention. It exists because governments say it exists, and because we all collectively agreed to pretend it does. In practice, what you are actually moving around is claims on central bank liabilities, represented as decimal numbers in databases that were never designed to handle cross-currency reconciliation properly. This matters enormously for implementation. When I built our multi-currency ledger, I had to accept that USD and EUR were not "real" in any engineering sense. They were string identifiers attached to different decimal precision rules, different settlement cycles, and different regulatory treatment. Treating them as interchangeable numeric types was the mistake that nearly bankrupted us.

How I actually implemented currency handling

Stop using floating point numbers for any monetary value. I cannot stress this enough. Every tutorial that tells you to use a float or double for currency is giving you garbage advice. Use integers representing the smallest denomination (cents, satoshis, basis points). Always. Our first implementation used BigDecimal for everything and still had rounding errors during high-volume periods. The issue wasn't precision, it was inconsistent rounding modes across different library calls. I switched to storing everything as long integers and only converting to human-readable format at the presentation layer. This eliminated approximately ninety percent of the reconciliation bugs we had.

Exchange rates need their own table with explicit timestamps and sources. Not one rate per day. Not a cached value from a third-party API that doesn't tell you when it updates. Each transaction needs to be tied to the exact rate at the exact second it occurred, with the source documented. I learned this the hard way when our provider silently changed their rate source without updating the API documentation, and our P&L statements didn't match the bank statements by about two percent over a three-month period.

The edge case that nearly killed production

There was a specific scenario involving ZWL (Zimbabwean dollar) revaluation that I still think about. Zimbabwe underwent a currency redenomination in 2009, removing twelve zeros. Our database had historical balances in the old currency stored as decimal values. When the new currency launched, we needed to divide every affected balance by one trillion while simultaneously accepting new deposits in the revalued currency. The workaround was building a migration script that used arbitrary-precision arithmetic through the Java BigInteger class, processing accounts in batches of five hundred at a time with checksums after each batch. We also had to handle the fact that some users had withdrawn funds in the old currency between the redenomination date and when we caught the issue. Those accounts needed manual reconciliation against bank records.

👉 Clique no botão abaixo para saber mais sobre o assunto!

This took us four days to complete correctly. It should have taken four hours if the system had been designed with currency evolution in mind from the start.

Common pitfalls that beginners miss

Triangular arbitrage in your own systems is the most dangerous issue. If your platform allows USD-to-EUR, EUR-to-BRL, and USD-to-BRL conversions, and you're using slightly different spread calculations for each pair, you can create situations where a user converts through the triangle and ends up with more money than they started with. I found one in production where the EUR/BRL rate was calculated with a different rounding interval than the USD/BRL and USD/EUR paths. The discrepancy was only about 0.03 percent, but at volume it added up to significant unauthorized inflation of user balances. FX fee stacking is another one nobody warns you about. When a user initiates a transaction in currency A and your settlement happens in currency B, there are typically at least three conversions: user currency to your operational currency, operational currency to settlement currency, and sometimes a spread on each leg. If you're not tracking and capping these explicitly, your actual cost of cross-currency transactions can be two to four times what the mid-market rate suggests.

Time zone handling in rate lookups seems trivial and it is not. The FX market operates continuously but rates are quoted with specific timestamps in specific time zones. If you're pulling rates from an API that returns UTC timestamps but your application stores them in local time, you can end up using a rate from the wrong market session. This caused a 0.15 percent systematic error in our USD/GBP corridor that went unnoticed for six months.

What I would do differently now

I would separate the concept of "currency" from "unit of account" entirely. A currency is just a standard of value within a jurisdiction. A unit of account is what your database actually tracks. These can and should diverge. Our most robust system stored all balances in a single internal unit (essentially a stable numéraire) and only converted to display currencies at query time. This meant exchange rate changes didn't require batch updates across millions of records. The downside is that reconciliation becomes slightly more complex because you need to maintain the conversion layer separately. But the alternative, which is storing every balance in every possible currency it might ever be displayed in, is unmaintainable at scale.

If you are just starting out and need something simple, look into libraries like Money and Currency from spf13, or the java.util.Currency class combined with a proper exchange rate service. Don't try to build your own decimal arithmetic. You will get it wrong. For production systems handling real money across multiple jurisdictions, the amount of infrastructure required is significantly higher than most people expect. The currency abstraction layer alone usually takes a dedicated team several months to get right. Plan accordingly.