Cronos Cashflow
A financial planning and cash-flow visibility platform: upcoming obligations, recurring entries, and projections.
Context
An in-house product. A financial planning platform built to give visibility into upcoming obligations, recurring transactions, and cash-flow projections, the kind of information that usually lives scattered across spreadsheets.
Challenge
The financial domain tolerates no ambiguity: one recurring entry projected wrong corrupts the whole forecast. The challenge is modeling recurrence, projection, and settlement so that any number on screen is auditable back to its origin.
My role
Software architecture, backend and frontend development, financial domain modeling, authentication, deployment, and infrastructure.
Responsibilities
- Software architecture and product modeling.
- Backend in PHP 8 with a relational database.
- Web interface in Next.js.
- Authentication and access control.
- Containerized deployment and infrastructure.
Constraints
- Correctness of the financial domain over delivery speed.
- Authentication has to serve three distinct clients: web, mobile app, and the legacy application.
- An in-house product with a small team: the architecture must fit the people maintaining it.
Architecture
- A backend organized into separate modules (application, API, shared library, and a console layer), with the console hosting scheduled routines and commands.
- JWT authentication serving web and mobile from the same API.
- A decoupled web interface consuming the API, with domain separated from presentation.
- A React Native mobile app sharing the same backend API.
- Containerized environment with Docker and docker-compose.
Main technical decisions
Keep a single backend serving both web and mobile, instead of splitting into services.
Why
The domain is cohesive and the team is small. A well-organized modular monolith gives the same clarity of boundaries without the operational cost of distributing the system.
Trade-offs
- Vertical scaling before horizontal.
- Requires internal module discipline. Without it, the monolith turns into a big ball of mud.
- Drastically reduces the operational surface: one deployment, one database, one place to debug.
Authenticate with JWT rather than server sessions.
Why
The same API serves a browser and a mobile app. Cookie sessions work well in the browser and poorly on mobile; JWT provides a single mechanism for both clients.
Trade-offs
- Token revocation needs its own strategy: destroying a session is not enough.
- Tokens need a short lifetime, which brings refresh complexity.
- In exchange, a single authentication flow for every client.
Model recurrence as a rule, not as pre-generated rows.
Why
Materializing years of future entries in the database freezes editing: changing one recurrence would mean rewriting the entire projected history.
Trade-offs
- Projection becomes computed, which costs more on read.
- Requires care with one-off exceptions inside a recurring series.
- In return, changing the rule immediately reflects across the whole projection.
Implementation
- Recurring and one-off financial entries.
- Cash-flow projection derived from recurrence rules.
- Dashboards and financial reporting.
- Role-based access control.
- Payment integration via Stripe.
Production concerns
- Containerized deployment.
- Scheduled routines executed through the backend console layer.
- Operations and support owned in-house.
Results
- A product in production, with web and mobile served by the same API.
- Turned recurrence rules into forward visibility of upcoming obligations, replacing manual spreadsheet tracking.
- A single authentication surface across the product's different clients.
Stack
- PHP 8.3
- MySQL
- JWT
- Stripe
- Next.js
- React
- TypeScript
- Tailwind CSS
- React Native
- Docker