Practices and tools for a startup
Tags: webdev, javascript, python, startup
Published: 2023-03-23 01:20:09

Approaches needed for a start-up are absolutely not suitable for large companies like Yahoo, Google or Amazon. 

The purpose of the article is to give a general idea of the "right" approaches when creating a startup.

### What approaches are needed for a startup?
1. Making a feature fastly is more important than following "best practice".
2. You can choose unstable libraries, but more convenient and functional which help for rapid evolution.
3. Bet on people who can make a feature here and now rather than on those who will do it right, but for longer.

These approaches work well in the short term, but after a relatively short time, problems may begin slowing down the pace of development:
1. **Coupling and cohesion of the code**
	- You can't just figure out what's going on in the code section without making 10 deep jumps. The speed of development gradually decreases.
	- It is impossible to split the code, to separate it into separate entities or modules or services because technical and business entities are closely intertwined with each other or because the module takes over too much.
	- In a couple of years, it will be easier to rewrite the entire project from scratch than to try to refresh and refactor the current code base. Examples: Photoshop, khan academy. You can name a few by yourself.
	- It may be necessary to rebuild the application a little differently for a new hypothesis. Again, high connectivity will prevent this. Instead of building the necessary application from the components brick by brick with improvements, you will have to copy-paste and make small changes in a lot of code sections. And God willing, you will have time to write tests before that.
2. **Bad DevExp**
	- Increasing cognitive load.
	- Semi-automated deployment -- every time you need to keep in mind some technical elements such as environment variables in order to perform a step-by-step algorithm that could be generally speaking automated at the level of a Bash script or CI\CD.
	- Partly manual formatting of the code. There are auto-formatters for almost all languages used in production. 
3. **Insufficient elaboration of the task before its transfer to development**
	It is fraught with repeatedly redoing the features, or the programmer will be forced to think about the possible states and transitions between them himself, taking into account the business domain nuances, which can take a lot of time, not to mention the increased cognitive load. Maybe this is a programmer in a startup?

### The recipe for overcoming problems is quite simple:
- If possible, write isolated code - low-coupling with high cohesion.
- Automate processes. The ideal is a ready-to-use development platform in which most technical issues are solved, which allows developers to focus on business-specific tasks. For small teams it is a luxury, for big teams it is crucial.
In a startup, start with strict naming conventions\paths\approaches - do not forget to document, or even better at the level of checks in the CI\CD, put into auto-formatters, pyinfra and look at [gitops] (https://about .gitlab.com/topics/gitops /), when the transition to Kubernetes is ripe.
Ideally, automate some checks at the pre-commit stage of a project based on agreements and force devs to use pre-commit.
- Detail tasks before transferring to development or lay down time for study in development.

A balance between long-term and short-term goals. Naturally, if possible, because most startups are constantly on the verge of collapse. There are things that, if not laid down at the very beginning, then they will shoot at an inconvenient moment - they will significantly slow down development if they do not force them to fix bugs most of the time.

We start a project from business entities. Our task is to clearly reflect business entities in technical models and implement business logic tolerably from the point of view of speed. You can rent or buy impressive capacities for relatively little money, and it is unlikely that it will be cheap to write a product from scratch. Therefore, you can choose not the fastest language like Python or Javascript and related abstract magic technologies, but you will fork out for a powerful server. It is the best way to build MVP for checking hypotheses than writing incredibly fast bulletproof code for most cases. 

### Selection of tools
1. Use what the team is best able to work with, or lay down time for transition and adaptation.
2. Get acquainted with [new](https://stackshare.io/posts/top-developer-tools-2022 ) related solutions that can solve some problems and speed up the development of a type of auto-generation of elements for the frontend based on design, or tools for creating internal tools,  specific CI\CD for mobile applications.
3. You can use tools that are currently in beta, nevertheless, these tools should already have a living ecosystem and an active contributor.

### Monolith or microservices?
Of course, firstly it is better to make a good monolith with clear interfaces for the libraries\modules than full-fledged microservices for all the best of the best practices. Maybe your product will not live up to the need for microservices, and it most likely will not live, but if it does, then you have low-coupling code and, possibly, autotests, which will make it easy to cut the monolith piece by piece into microservices.

### Environment
There is no more painful thing than repetitive necessary time-consuming steps to run or build an application. The environment should not make you suffer by doing monotonous actions to launch the service and test a new feature or catch a bug. Ideally, this is one command - and written in a README file - for each environment without a long wait, when the service code is checked for quality, assembled and rolled out to dev stand.
[pyinfra](https://pyinfra.com /) -- take a closer look to automate processes at the initial stage.


### ORM or NOT for ORM?
- There are a lot of ORM libraries for various especially high-level languages. It is okay for a really simple CRUD application. For something at least somewhat complex (2+ JOINs) and/or especially performance - only raw SQL queries I would suggest.
- There is an additional level of abstraction between the technology and your code, which may limit you or, most unpleasant of all, it will put an unobvious bug after updating the library at the most inconvenient moment.
- ORM dialect can be updated to the major version and, surprise, all your ORM code has become a legacy. 

### GraphQL or REST API?
Selection criterias: 
- Developer's experience.
- Configuration of backs\fronts. Where do you want to shift the work of getting data from the backup? 

IMHO, it is better REST in most cases, because the frontend focuses on designing, and endpoints can be written around business entities, thereby creating a clear visual structure.

### Database
Most likely, you will have enough of SQLITE to test the hypothesis. If you are creating a mobile application, then take a closer look at [firebase](https://firebase.google.com /) or [PocketBase](https://pocketbase.io /).

PostgreSQL is a wonderful database, but take into account the overhead costs of hosting, monitoring, configurations and dumps -- administration.


### Containers
Docker - must-have. It has a lot of documentation and a large community, any issue can be solved very quickly.
Docker-compose - when containers become more than 1.
Kubernetes + [rancher](www.rancher.com ) -- when you have money for a DevOps engineer.

### Low code, no code
There are a lot of solutions on the market for websites, [mobile applications] (https://flutterflow.io /), frontends ([locofy](locofy.ai )), backends.
Keep in mind that powerful and low-code multifunctional solutions without code sometimes require a long study. And, again, this is an additional level of abstraction, which means less control and restrictions.

### Internal tools
For what? To automate internal business and technical processes.

[budibase](https://budibase.com /) low-level open-source code platform for creating internal tools, workflows and admin panels in minutes. Supports PostgreSQL, MongoDB, Rest API, Docker, K8s and more.

[re-tool](https://retool.com /) is not open source, but also good.

### Monitoring and metrics
- [uptime-kuma](https://github.com/louislam/uptime-kuma ) -- a minimalistic multifunctional thing to understand that your service is alive. There are integrations for alerts.
- [prometheus](https://prometheus.io /) + [grafana](https://grafana.com /) -- the earlier, the better. It will give an idea of how your service is used by technical and business metrics.

### Files
If you just have files, then any s3-like bucket will suit you. If you need to store media files and especially do transformations with them, then take a closer look at [download.io](download.io) and https://cloudinary.com/

### PWA
Maybe PWA is suitable for the first version instead of a mobile application? You will save a lot of time, and you are unlikely to get to the top of apps store quickly.
In addition, some solutions also allow you to build a native application from the PWA.

## Uber starter pack for MVP
- [ruff](https://github.com/charliermarsh/ruff ) for Python, [rome/tools](https://github.com/rome/tools ) for JS
- sqlite / pocketbase / firebase
- piinfra
- **pre-commit**
- Docker
- Gitlab git flow