"Every financial system handles money. Surprisingly few model it correctly."

Most software developers have heard the advice:

Never use floating-point numbers to represent money.

The usual recommendation is to replace floating-point numbers with decimal types. While that avoids many precision issues, it still misses the real problem.

Money is not a number.

Money is a business concept.

And confusing business concepts with implementation details is one of the most common reasons financial systems become expensive to maintain.

The Difference Between Data and Meaning

A decimal value tells us almost nothing.

100.00

What does it represent?

  • 100 SEK?
  • 100 euros?
  • An invoice total?
  • Outstanding balance?
  • VAT amount?
  • Foreign exchange rate?

The number alone has no meaning.

The business concept gives it meaning.

Primitive data losses all the business concepts.

Money Has Behaviour

In many systems, money is treated as a primitive value.

In reality, money carries rules.

Those rules belong to the domain—not scattered across services, controllers, or database queries.

It knows:

  • which currency it belongs to
  • how it should be rounded
  • how many decimal places are valid
  • whether it can be added to another amount
  • how it should be formatted
  • when an exchange rate must be applied
  • how gains or losses should be calculated
  • which accounting period it belongs to

These are not implementation details.

They are business rules.

A Money object should protect those rules instead of relying on every developer to remember them.

Primitve numbers can't represent Money objects.

A Simple Example

Imagine two values:

100 SEK

50 EUR

A decimal implementation happily adds them together.

100 + 50 = 150

From a programming perspective, nothing is wrong.

From a business perspective, everything is wrong.

Currencies cannot be added without first applying an exchange rate.

The software should prevent this from ever happening.

A well-designed Money object makes invalid operations impossible rather than hoping developers remember every rule.

Small Errors Become Expensive

Financial systems rarely fail because of one large mistake.

They fail because thousands of tiny mistakes accumulate over time.

A one-cent discrepancy may seem insignificant.

One cent won't wake anyone up.

Ten million one-cent differences will stop an entire reconciliation process.

Suddenly those tiny differences become reconciliation breaks, manual investigations, delayed settlements, customer complaints, and regulatory reporting issues.

I've seen systems where two perfectly valid applications used different rounding rules. Individually, both systems produced correct calculations.

Together, they produced different financial results.

Neither system was technically wrong.

The architecture was.

Business Concepts Outlive Technology

Programming languages change.

Frameworks change.

Databases change.

Cloud platforms change.

Business concepts remain.

Money has existed for thousands of years and will continue to exist long after today's programming languages have been replaced.

Architecture should therefore model the business first.

Implementation comes second.

This is why financial systems benefit from strong domain models.

The domain model represents reality.

The code simply implements it.

Beyond Financial Systems

Although this example comes from banking, the principle applies everywhere.

Throughout software architecture we repeatedly encounter concepts that should remain independent of implementation.

An information model is not a database model.

An account is not a transaction.

Architecture is not a framework.

Requirements are not implementation.

Business concepts are not programming types.

Money is simply one of the clearest examples.

The role of architecture is to protect these business concepts from becoming implementation details.

Because technologies change.

Business concepts endure.

AI Doesn't Change This

Modern AI is becoming remarkably good at generating software.

It can produce classes, APIs, tests, and even complete applications.

But AI cannot invent your business model.

If your architecture tells the AI that money is simply a decimal value, it will faithfully generate thousands of lines of software based on that assumption.

The result will be consistently wrong.

AI amplifies architecture.

AI will produce code faster, good or bad.

A good architecture produces better software faster.

A poor architecture produces poor software even faster.

Designing for Financial Systems

This principle extends far beyond money.

Many financial concepts deserve their own models:

  • Money
  • IBAN
  • BBAN
  • Bank Account
  • Settlement Date
  • Exchange Rate
  • Interest
  • Tax
  • Payment Reference
  • Balance
  • Working Capital

Each carries its own rules, constraints, and behaviour.

Treating them as strings, integers, or decimals moves business logic out into the application, where it becomes duplicated, inconsistent, and difficult to maintain.

Encapsulating these concepts inside the domain keeps the rules in one place and allows the software to protect itself.

The Architect's Responsibility

Good architecture is not about choosing the latest framework.

It is about modelling reality accurately.

When implementation details become more important than business concepts, the software slowly drifts away from the business it was built to support.

That drift is rarely visible during development.

It becomes painfully obvious during audits, production incidents, regulatory changes, and large-scale maintenance.

The most expensive systems are rarely the ones with poor code.

They are the ones with poor models.

Final Thoughts

Software doesn't fail because developers use decimals.

Software fails because we confuse implementation with business.

Money isn't a decimal.

It never was.

It is a business concept with behaviour, rules, and responsibilities.

Technology changes.

Business endures.

Architecture exists to bridge the two.

Money is not a number.