Skip to main content

Rust Backtester - Application Architecture - Part 2

·731 words·4 mins
Anthony Ori
Author
Anthony Ori
~ tinkerer ~

In the previous article we covered the system-level architecture. In this article we will go through the application’s architecture.

graph TD

U[Users / Browser]
FE[Frontend App
UI] API[Backend REST API] DB[(Database)] U --> |HTTP Request| FE FE --> |HTTP Response| U FE -->|HTTP Request| API API -->|HTTP Response| FE DB -->|ETL| API API -->|Write| DB

The setup follows a microservices architecture. The flow is: the user’s browser requests are sent to the frontend app that holds the User Interface (UI); the frontend app speaks to the API that holds the meaningful data; the API speaks to the database. At any point in the request/response chain, if the frontend app can serve a response without involving the backend layer, it will. Ditto for the API w.r.t. the database.

Why use microservices when a monolith is just fine?
#

After all, a monolith would’ve reduced system complexity, on paper at least. The backend of the app has historically been its own thing, and used to run via Command Line Interface (CLI). I later decided to expose the features to the world via UI, and as such the frontend app was born.

The separation of the whole into parts makes it easier to develop one without affecting the other. This flexibility allows external users to use the app but doesn’t stop the backend from being used offline via CLI.

Pros
#

  • splitting UI from data makes it easier to outline the responsibility boundaries between the parts;
  • UI can change without affecting logic and data;
  • logic and data can change without affecting UI (*)
  • UI layer has no access to the database
  • can add new features without worrying about everything else falling apart
  • each app can be deployed separately (very good for CI & CD since the feedback loop is shorter)
  • debugging is easier

(*) Sort of. The UI still needs to be in sync, even if not fully, with the data to render it correctly. There are ways to tackle this. One of the popular ones is GraphQL, which claims to be an alternative to REST APIs. Unfortunately, I don’t have enough wrinkles on my brain to understand how GraphQL benefits a fullstack developer, or a team of. A fullstack developer can simply enforce the contract between UI and backend, outright.

Similar to the consideration of not using Docker in the previous article, GraphQL simply adds a layer of complexity without solving any problem.

If there’s no fullstack person, and a frontend-only and backend-only developer, then a case for GraphQL could be made, but only if the two parties cannot communicate with each other for a valid reason. Even if that were the case, I would still argue that something like the JSON:API standard:

https://jsonapi.org/

would be better, as it doesn’t require learning a new language or tool – it’s just JSON after all; and allows all parties involved to follow the agreed convention and focus on developing rather than ancillary issues.

Cons
#

  • the initial separation between UI/frontend and API/backend can be hard to reason about
  • need keep frontend and backend in sync – a monolith makes this easier
  • testing is harder because of more moving parts

Tech stack
#

  • Tailwind CSS – for styling
  • Dioxus Web – for the UI
  • Dioxus Fullstack/Server (*) – for the server and middleware layer
  • a CSV database (**)

Isomorphic Rust, is that a thing? What is it the future?

I remember when isomorphic Javascript was the rage and wished that we would come to a time when a server-side language could be used for frontend development. That wish was granted and Dioxus happened.

(*) It’s more Axum than Dioxus Server due to the fact that I had to strip out the Dioxus parts and use Axum directly. Not a dig at the Dioxus team, they’ve built something amazing!

(**) That’s right! For a backtester, I’m currently getting away with no database. However, the code is structured in a way that the CSV files can be swapped for SQLite, or something more robust like PostgreSQL, if needed, without affecting other parts of the core engine.

The sexiest part of a backtester is not the database or the server after all, it’s the actual backtesting, right? Right! But we need to get the boring parts out of the way first, don’t we?

In the next article we will cover some of the actual application code, at a high level.


Feel free to share the article on socials: