Skip to content
My Projects
Case study 2026

FinanceOS MX API

Enterprise-grade REST API for managing personal finances in the Mexican financial ecosystem: accounts, cards, transactions, budgets, loans and investments in a single API.

  • Java
  • Spring Boot
  • PostgreSQL
  • Maven

The case study

Problem
In Mexico a person’s financial life is scattered across banks, fintechs, SOFIPOs and wallets, each with its own app and format: there is no single place to check what you have, what you owe or what you spent.
Solution
A modular monolith in Java 21 and Spring Boot 3 —17 business modules with single-direction dependencies—, stateless JWT security, PostgreSQL with Flyway migrations, RFC 9457 errors and one non-negotiable rule: the balance is never mutated directly, it is always a consequence of the transactions.
Outcome
Full roadmap shipped (10 of 10 phases): auth, accounts, cards, transactions, planning, liabilities, investments and reports, with OpenAPI/Swagger, GitHub Actions CI and a final self-audit phase covering architecture, security and test coverage.

Process

Development process

The reasoning behind the technical decisions: why each technology was chosen, what challenges came up and how they were solved.

  1. 01

    Modular monolith, single-direction dependencies

    Each business context (account, transaction, budget, investment…) lives in its own module with its own controller, service, repository, DTOs and exceptions; JPA entities are never exposed through the API. Before writing code I documented conventions, security and the data model, and when a validation required breaking dependency direction —like blocking account closure by querying cards— I dropped the validation rather than violate the architecture.

  2. 02

    Money as a domain invariant

    Money is always BigDecimal, UUIDs are application-generated, timestamps live in UTC and every schema change is versioned with Flyway. The core rule: an account balance only changes through a single internal mutation point that records the transaction in the same step, preserving the one-way transaction → account dependency. Derived values —budget spent, next billing, returns— are computed per request and never persisted.

  3. 03

    Live verification, not just tests

    Every phase closed by running the real packaged JAR against a clean database and verifying with curl, on top of JUnit 5 and Mockito tests. That practice caught the bugs tests were masking —like a LazyInitializationException invisible under transactional tests— and the final phase was a self-audit: forbidden inter-module dependencies, mappers touching lazy relations, duplication and a security review. Architecture rules do not enforce themselves; they must be audited.

Repositories

Commits

  1. V1

    dd562c2Eduardolast week