Choosing a technical stack that fits your organization's needs can be tough. When choosing the technology to build your product, there are a few things to consider:
The experience of the team
The impact on recruiting efforts (e.g., how easy will it be to find these skills)
The ability to execute fast and to maintain quality
We took all of these points into heavy consideration when choosing the Komand tech stack. Below is a breakdown of what we chose, why we chose it, and how it fits (or sometimes doesn’t fit) our needs.
CI - Drone
Drone is small, easy to use CI system. Installation was a breeze and maintenance has been pretty simple. While you may get (potentially?) more power out of a larger build system such as Jenkins, at the stage we are it we simply did not need that much complexity in our build process.
You choose which Docker images you want your build to use and hit the ground running. Matrix builds, which were recently added, also allow a ton of flexibility to the CI process, and bring some much needed features that people from the Jenkins realm would really miss.
Development Environment - Docker
Docker enables us to bring new developers up to speed and committing code right away. We can create reproducible development environments via Docker Compose. Want to run our codebase? Download docker, cd into repo directory, and docker-compose up.
Backend - Go
Go is a simple language that allows you to do tons of complex tasks. It has a simple syntax (think dynamic programs such as Python and Ruby). This makes the language easy to understand and use.
I would argue that “gofmt” is probably one of the best parts of the Go ecosystem. No more arguing about coding styles and conventions--it’s baked into the language. Additional tooling like pprof and the race detector help profile and debug code easier.
The Go community is one of the most passionate and energetic communities of which I have ever taken part. Although there are many disagreements, in general I believe everyone is trying to continually make the Go ecosystem enjoyable, efficient, and effective.
Pain Points & Observations
Some friction we faced included package management. There is a great initiative to standardize on package management because it is a huge pain point in being able to create reproducible builds.
One observation I’ve made about the Go community is that once you start seeing tons of packages crop up that all serve the same functionality, it usually means there has not been a good solution for it yet. One great example of this is with the 50 routers exist currently. It’s a headache to choose something that just works. Go1.7 partially addressed this specific issue by introducing Context to the net/http package which I think is a great step forward to eliminating the need for the routers that all provide their specific Context objects.
Backend - Docker
Docker is also integrated right into our product. As a job is running for a particular workflow, each step contains a plugin. Each of those plugins are run in a container. This allows us to run tasks such as spinning up a Cuckoo sandbox, fire off API calls, etc. We are able to run containers, execute plugins on the fly, and easily tear down.
This also makes it incredibly easy for people to contribute to our plugin collection. As long as you follow the plugin specification and accept input on STDIN and write to STDOUT, it doesn’t matter what language you use.
Frontend - React
Lower the Barrier
Componentize All the Things!
Components are awesome. Functionality is contained to one file. We can have container components that deal with data, dumb components that deal with primarily UI so we don’t need to deal with CSS when writing code, stateless functional components that render purely based off props, higher order components that abstract away common functionality, the list goes on.
And in my opinion, the more components the merrier. If I see too many DOM elements in development, I usually think to myself, "I could potentially use a component here."
Core Component Libraries
React becomes incredibly useful if you are creating a UX pattern library as you start to scale. Getting a great designer early on is essential to having a solid UX pattern library and creating a Component library that matches one to one early on greatly increases the speed at which future front-end engineers can execute features.
We've been asked severals times why we chose the technology that we did to build Komand. A tech stack is mostly a sum of its parts. If the individual pieces don't work well together, it slows everything down.
We took all the gains and limitations into consideration when choosing all the languages and frameworks in our stack, and hope that this explanation is valuable in helping you consider yours.