🇵🇸 Free Palestine 🇵🇸

Spaghetti to Scalability 🌟🌟

Cover image

The Problem

In the fast-paced world of startups, we often rush to add new features without looking back. After three years of this “move fast” approach, our code became a tangled mess, making debugging a nightmare, and even simple database changes felt impossible.

This blog is about our journey from chaos to order. We’ll explain the problem, share our thoughts, and describe the steps we took to clean up our code and make our system work smoothly. If you’re facing a similar mess and want to learn how to make things right, keep reading.

Thoughts

My general thoughts to solve the problem is:

  • refactor codebase
  • monitor everything
  • optimize bottlenecks

after monitoring and optimizing we can decide whether we need to scale vertically or horizontally

Refactor

Am doing them in 2 steps which is simpler.

1- Soft Refactor (copy/paste)

I don’t know if this term exists but anyway, I will find it

in this refactor we don’t change anything in logic or flow, just make the code cleaner and simpler by copying/pasting things.

soft-refactor process

  • split features: long files divided into smaller ones for example instead of having all db models inside models.py you create models dir and create files inside it <feature_name>_models.py and the same for views, signals, tasks, and so on

  • views should be short: take input from request and pass input to the right controller then return the response it shouldn’t have the logic inside it

  • DRY: move shared repeated logic to the utils folder

  • group things: related things should shown grouped, for readability and I mean functions, URLs, serializers, etc

after this process you will have cleaned files, simple views, and most complex parts are moved to controllers

which is fine for now and this will boost our speed in the next steps

2- Hard Refactor

unlike the last step this will be dangerous if you don’t have tests or your tests don’t cover enough cases

but enough copy/paste and let’s do this.

hard refactor process

  • remove duplication: now complexity lives in controllers mainly check duplicates and try to write more general functions/mixins that do general cases with variables

  • viewsets: use generic viewsets this will allow you to make much with less code

  • library: use famous libraries for the common tasks

  • encapsulate things

  • code design: think deeper to find if there is a design pattern that will make things simpler

  • SOLID: try to apply clean code principles as you can but keep in mind don’t over-engineering or waste time

  • Database: avoid it as much as you can but is mandatory to keep in mind this

    • when applying database normalization keep in mind this code in production :D
    • if you decide to add a new table/column you should copy data to this new ones
    • if you decide to move table/column you should add them as computed properties on the model so the code doesn’t break or the structure changed in the frontend response
    • also think about how much data are in this table how long migrations will take, and during this time you will use database replicates or what
    • add/remove indexes that will boost the performance

after this process, you will test if everything is working right but also debug process is simple now because the code is much better

Monitoring

How can you drive a car with closed eyes ?!!

Open your eyes, and observe your system so you can make the right decision for your startup.

Tools

  • basic logging
  • grafana
  • prometheus
  • django-slik
  • etc…

just search and you will find tons of tools very powerful will help you