Architecture Decision Record
Status
accepted
Context
FinReview needed to support portfolio analytics, AI-generated insights, market data aggregation, authentication, and alerting. The choice of backend architecture would shape how each of those capabilities was built, tested, and deployed. A traditional server-side rendering approach was considered alongside an API-first design.
Rationale
An API-first architecture places all business logic in the backend and keeps the frontend as a pure presentation layer. This separation makes each capability independently testable, independently deployable, and independently evolvable. FastAPI's async-first design matches the IO-heavy workload of a financial application aggregating data from multiple external sources.
Trade-offs
An API-first architecture introduces deployment complexity — the frontend and backend are separate artifacts with separate hosting requirements. For a smaller project, a monolithic PHP or Django application would be simpler to deploy and operate. The additional complexity was accepted deliberately because demonstrating clean service boundaries was the primary goal of the project.

Before writing a line of FinReview's code, I made a decision that shaped every subsequent architectural choice: the backend would be an API, and the frontend would be a consumer of that API. Nothing else.

This is a common pattern in modern web development, but it was not the natural starting point given my background. Thirteen years in enterprise CCM platforms meant most of the systems I had worked with were server-side rendering applications where business logic, template rendering, and data access were tightly coupled by design. That coupling worked for document generation and communication management. It would not work for what I was building.

FinReview had to do several things simultaneously. Portfolio analytics required accurate financial calculations. AI briefings required calling external LLM providers with graceful degradation. Market data required aggregating from multiple sources — Yahoo Finance for equities, mfapi.in for Indian mutual fund NAVs — with different rate limits and response formats. Authentication required verifying tokens on every protected request. Alerting required evaluating rules against live prices.

If those responsibilities lived in a monolithic application, they would inevitably become entangled. A change to the analytics logic would require testing the entire application. A failure in the news ingestion service would affect the portfolio view. The AI layer would have direct access to the database.

An API-first architecture separates these concerns by construction. Each capability is a service. Services communicate through explicit contracts — the API. The frontend knows nothing about how portfolio analytics work; it knows only what the analytics endpoint returns. The AI layer knows nothing about how prices are fetched; it knows only that when it needs market context, there is an endpoint for that.

I chose FastAPI specifically because it enforces this separation well. Every route has an explicit request model and an explicit response model defined in Python types. The automatic OpenAPI documentation at /docs is generated from those types — there is no separate documentation to maintain. The async support handles the IO-heavy workload naturally: while one request is waiting for a Yahoo Finance response, the event loop handles other requests rather than blocking a thread.

The trade-off I accepted was deployment complexity. A static HTML frontend and a FastAPI backend are two separate things to host, configure, and keep in sync. For this project, the frontend runs on static hosting and the backend runs on Render. They communicate through a CORS-configured API endpoint. That configuration adds friction that a monolithic application would not have.

I accepted this trade-off deliberately. The project's purpose is to demonstrate architectural thinking, not to minimise operational effort. The clean separation between frontend and backend is itself part of what the project demonstrates.

The more significant lesson was about the influence of early decisions. Choosing an API-first architecture at the start meant that every subsequent capability — analytics, AI, alerting, news, authentication — was built as a service from the beginning. When the authentication implementation needed to change from an unsigned token to an HMAC-signed token, the change was isolated to the auth routes and the token verification function. Nothing in the analytics or AI layers needed to change. That isolation was a consequence of the early architectural decision, not an accident.

Architecture decisions made at the start of a project have an outsized influence on the velocity of every decision that follows. Getting that first decision right is worth more than any subsequent optimisation.

← Choosing appropriate security over maximum securit…
Why financial calculations should never touch a la… →