I was able to reduce my web services’ memory consumption by 3-4x last week. See the full post for a step by step deep dive.
My tech stack is Render, Django, and React. My code was experiencing a looongg lag time in all of its views (controllers if you’re a ruby on rails expert). My DB at the time only had 70+ jobs postings and it was taking 30 seconds to load. Further, it was a single 500 word article and it was taking 15 seconds to load. I’ve used the same architecture for my blog sites many times and this is a first.
This can have a lot of different implications, but for a job board it deeply affects the UX and the SEO.
The solution turned out to be to remove the spaCy library. It’s an NLP library which I used to grep for nouns and verbs in job postings. The corpus that it uses is enormous. For example, the default English language model
en_core_web_sm is relatively small, typically around 11-15 MB in size. Larger models like
en_core_web_md are around 50-100 MB, and even larger models like
en_core_web_lg can be several hundred megabytes in size. I was loading the package in my views file as a global -
nlp = spacy.load("en_core_web_md").
My use cases for it is a high-powered regex and parser to generate json data from web pages. I could use the openai api to do this, but spaCy is completely free and deterministic in the way that I need the code to be.
I have a single monolith for my project. It houses my frontend, backend, and crons.
What I did was make a new branch
techstackjobs_celery and proceed to rip out all the frontend architecture, static directories (30-40% memory improvement),
node_modules, and loaded
spaCy onto the code. Then I added a background worker to Render and used this branch.
I kept the frontend, views, and the staticfiles in this codebase, but removed the spaCy library and all the Celery tasks. In the celery tasks, I made sure to load the corpus as a global. The way that deploy engines like Render or Vercel work is that each tasks is allocated a certain amount of memory. The cron library you use doesn’t typically default provide it so they set it themselves to avoid huge crashes in their servers. If I loaded spaCy in a task, this would immediately crash and give me a
SIGKILL, breaking all my future tasks until I restart the server.
My Render dashboard
Hide from Techstackjobs