How we chose a tech stack for our startup

Lim Yi Sheng
Helicap Engineering
6 min readJan 7, 2020

Welcome to the first post from Helicap’s engineering team, where we will try to bring you through our tech stack, and explain how we ended up with the choices that we made.

For those who do not know Helicap, we are a FinTech investment firm specialising in the alternative lending space in the Asia Pacific region. We help people improve their livelihoods by driving financial inclusion and enabling our partner platforms to transform the way consumers and SMEs access credit today.

To build a startup, the first step is always the hardest; and this goes double for any tech enthusiast in a startup. One of the reasons why software engineers gravitate towards startups is the freedom that it brings. However, this often brings with it the problem of paralysis of choice. Our engineering team too spent quite a considerable amount of time evaluating pros and cons of each technology choice. We were Goldilocks locked in a house with infinite bowls of porridge with an infinite range of temperature.

As such, we decided that an overarching philosophy was needed first in order to lay common ground, and we will subsequently select each aspect of our tech stack based on our common philosophy.

Philosophy

At Helicap, we are big fans of Gall’s Law:

A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system.

In short, Keep It Simple, Stupid.

We are also big fans of YAGNI. You Are Not Gonna Need It. Or in the words of Ron Jeffries:

Always implement things when you actually need them, never when you just foresee that you need them.

But that does not mean that we should build things without consideration for the future; it just means that we don’t over-engineer.

With those two guiding philosophies, we created our own rubrics to judge a technology.

  1. Simplicity. Is the framework/technology easy to grasp? Does it contain any complexities that we do not need?
  2. Need Fulfilment. Does the framework/technology fulfil our current needs?
  3. Extensibility. Even if we are not going to implement certain features, how confident are we that said framework/technology may be able to scale/extend towards the future?

Frontend

For our frontend choice, after taking into consideration maturity, and community support, the top two contenders came out to be a fight between Angular and React, both of which are always ranked in the top web frameworks to use in StackOverflow’s Developer Survey.

However, we need to see how they stack up against our rubrics.

Simplicity

Angular is a full-fledged framework for UI development, whilst React, is a more lightweight library. While we are absolutely confident in Angular’s capabilities, we felt that Angular was more complex to understand, with many opinionated intricacies built into its framework, whilst React was far easier to pick up once a project structure was defined.

Winner: React

Need Fulfilment

Both of these technologies really served to fulfil our needs, which was to build a reliable and robust frontend. We think that no one will really go wrong with either one of them.

Winner: Draw

Extensibility

Given the maturity of both these technologies, we believe that both of them will be able to fulfil any future needs that we may plausibly have.

Winner: Draw

Our Choice : React

Backend

For our backend choice, we had two options that were tabled. The first was Java using Spring Boot. This was a framework that our team felt the most comfortable with, having had some prior experience building applications with it before. Our second choice was one that rose out of the results of some experimentation; and that was Go.

After a few months of development with each, we felt confident in our ability to judge each technology against our rubrics.

Simplicity

One obvious difference we noticed is the declarative nature of Spring Boot’s annotations, versus Go’s largely imperative way of coding. For Go, there is little reliance on dependency injection, and everything is handcrafted. Whilst in Spring Boot, most of the dependency injections are handled by annotations and configurations. This is convenient, but at times, these can also invert control and add more complexity when optimising certain aspects of Spring Boot. While, the initial process of having to handcraft Go’s infrastructure had rather annoying pains to overcome; but once we had something of a pattern going on in our code, we could really focus on writing business logic.

Winner: Go

Need Fulfilment

Both of them fulfilled our needs quite nicely. Spring Boot has a superb ecosystem, while Go’s libraries really catered to all our requirements.

Winner: Draw

Extensibility

Given the maturity of Java, and Spring Boot, we are confident that it can take any number of kitchen sinks that we care to throw at it.

Go, on the other hand, is still an up and coming language. However, the huge community support, as well as the ability to call C libraries actually gave us a huge sense of security with regards to the extensibility of this language.

Winner: Draw

Our Choice: Go

Database

NoSQL vs SQL. Those are murky waters I dread to wade into.

But wade into these waters, I must.

So for our database choices, our team was split rather evenly between Postgres and MongoDB.

Simplicity

Considering that both of these databases have simple one-click managed services (Aurora PostgresSQL and Mongo Atlas for example), most of the complexities are taken off our hands.

Winner: Draw

Need Fulfilment

For our startup, we needed to process documents of varying data types and structures, of which, some of them have a tendency to change sporadically without any notice. In short, we have a lot of unstructured data to process on a regular basis, which NoSQL seems to be the better option for.

Winner: MongoDB

Extensibility

Given the maturity and community support of these two technologies, we believe that both of them will be able to fulfil any future needs that we may plausibly have.

However, one really interesting feature we would like to highlight is the change streams introduced with Mongo 4.x. This opens up possibilities for us to use change streams for audit trails, event sourcing, and in memory caching. We will definitely elaborate on this further in future articles.

Winner: Draw

Our Choice: MongoDB

Conclusion

So after a couple of rounds of evaluation and prototyping, we managed to successfully decide on a tech stack that we feel is well positioned to serve our needs. What really saved our bacon, was deciding on a common team philosophy that all of us could really get behind. And once that was established, selecting our choices became a lot simpler.

However, all of us are also cognisant of the fact that all of this is not set in stone. As they say, change is the only constant in a software’s lifecycle! What we want to ensure is that we build our software using established software design patterns and principles. By maintaining the modularity, extensibility, scalability, and resilience of our platform, we are then best equipped to handle any change and future needs of the platform gracefully.

We will be elaborating a lot more on these principles, as well as various challenges we faced along-the-way and how we overcame them in future articles. So do watch this space!

Thank you for reading this article, and we hope that this has helped in providing more clarity in choosing a tech stack for your startup too.

--

--