Technology at Just
A modern stack for scalable financial startups
At Just, we are building financial risk management systems for corporate treasurers, which requires us to handle large volumes of market data in real time, plus handle customer data and transactions with the security and reliability of a financial application.
Being a late seed-stage startup, Just needs to iterate quickly and minimize time spent on tasks that don’t deliver value to our customers and shareholders. The technologies used at Just need to be dependable and scale easily, while at the same time being easy to work with and not demanding too much engineering time.
As a team (Andrea, Anton, JP, Mikael & Simon), we’ve spent a significant amount of time researching, testing and optimizing our stack, and we believe that the foundation we’ve built may be well-suited to many other companies and applications.
Infrastructure
Docker, Kubernetes, Google Cloud Platform
Loosely, we operate our applications as a set of microservices — we have services which handle FX market data, customer transaction history, users, companies, notifications, and more.
These services are deployed as Docker containers and hosted as pods in Kubernetes clusters. We’ve chosen to host our clusters on Google Cloud Platform (GCP). Google offers a friendly interface and a generous startup subsidy package. We generally try to avoid GCP-specific technologies to avoid vendor lock-in or dependency on proprietary client libraries.
Front-end
React, TypeScript, Stencil.js, Stylus, GraphQL
Just delivers our product as a web-based SaaS application. This is implemented as a React application, which we continue to believe is a solid choice for a front-end framework. Our React components are written in TypeScript, since we generally favour static type systems, and styled with Stylus.
We’ve also developed our own “Just Elements” UI library. This is a set of web components compiled using Stencil.js, which can also be re-used in non-React front-end apps.
Our front-end is served by a GraphQL server, which helps us serve the correct data to each component without the need for overly specific or generalized REST endpoints.
Back-end
Go, Java 11, gRPC
Most of our backend services are implemented in Go. We’ve found Go to be a highly versatile language with a very favourable learning curve — developers with no experience of it can become productive quite rapidly.
The services which handle our financial market data streams are implemented in Java 11 (with Vert.x), since we rely on some Java-specific financial libraries.
One of the most important and valuable choices within our stack is the use of gRPC for our server-side communication (both request/response and streaming). gRPC enforces strongly typed APIs, which make remote service calls no more difficult than a local function call when implementing client logic.
gRPC services transmit Protobuf messages — a binary format which offers strong contracts between services. Essentially, we treat Protobuf as the shared “source of truth” for many of our data structures. This approach shifts many bugs that would be discovered at runtime with REST microservices to compile time.
Our application data is stored in a Cloud SQL Postgres instance, which seems like a largely uncontroversial choice.
Data Science
Timescale DB, Python, Jupyter Notebook, Metabase
Financial data analysis is at the absolute core of what we do, and as well as proprietary data from our corporate customers, we also hold a large data set of financial market data to support this.
Our historic FX market data is stored in Timescale DB (an extension of Postgres) containing almost 20 billion records. Timescale optimizes for time series data by generating a set of “hypertables”, making reads remarkably fast, even with an instance this size.
Our data analysis logic is often prototyped in Python, and we have recently started using Jupyter Notebook for data visualization. As our analytical algorithms mature, we integrate them into our application stack as a set of Go libraries.
We have also deployed Metabase, which provides a very simple way for us to build high-level data visualizations on a dashboard. This gives us quick snapshots of, for example, the average FX cost across all our customers.
Security
Keycloak, Open Policy Agent
We’re using OpenID Connect (OIDC) through Keycloak for user authentication. The solution is highly customizable and extensible, and allows us to have full control by running our own OIDC provider. This also allows us to seamlessly integrate a number of third-party solutions.
For authorization, we’re using Open Policy Agent, which allows us to write concise authorization policies.
Build Pipeline
git, Bazel, GitLab CI
Like many others, we use git for distributed version control, and we have elected to develop our main app within a monorepo.
We use Bazel to build the entire repository. This includes front-end components, where we’ve recently migrated the build process to use Bazel exclusively. We’ve been using Bazel for some time and it’s only just reached v1.0. However, it’s lightning fast even when building a large project.
We use GitLab CI to run our build and deployment process, with our own self-hosted GitLab CI runners with Bazel installed.
Landing Page
Gatsby.js, Sanity.io, Netlify
We’re of the view that marketing sites should be frictionless to operate, so our engineers can focus on app development. Our landing page at gojust.com is built as a static site with Gatsby.js, pulling content from Sanity.io CMS, and is hosted on Netlify. This setup makes it highly responsive and customizable compared to a dynamic site built with a more traditional CMS.
The Future
Vault, Istio
We try to maintain a balance between using stable technologies which have been battle-tested at scale, and constantly looking to improve the way we do things. At the moment we’re particularly focused on strengthening our infrastructure to ensure it doesn’t become a bottleneck as Just grows.
We’re currently in the process of implementing Vault for simpler, more secure secret management.
It’s also highly likely that at some point next year we will implement a service mesh such as Istio in order to further increase security and observability.
Conclusion
This list isn’t exhaustive, and it will undoubtedly continue to evolve in the future. However, we feel it gives us a very stable foundation to deliver solid, scalable financial applications while still developing and releasing rapidly.
We’ve created a pipeline and stack that we collectively enjoy working with, which is an important differentiator in the startup ecosystem where attracting talent can be a challenge. Our stack is, for the most part, efficient, frustration-free, and caters to many of our preferences around working and coding style. It’s also given every one of us the opportunity to learn new technologies which we hadn’t used previously.
For all of us, this is what sets working at Just apart from the larger companies from which many of us have come.