What "Stateless" Actually Means
Backend EngineeringJul 30, 20263 min read

What "Stateless" Actually Means

Stateless doesn't mean no memory, it means deciding where that memory lives. A breakdown of what statelessness actually buys you in a Django/Celery stack, and why it's the backbone of horizontal scaling.


What "Stateless" Actually Means

Your server just crashed and restarted. Did anyone notice?

If the answer is no, you're probably running something stateless. If the answer is "yes, everyone got logged out and lost their cart," you've got state living somewhere fragile.

The Problem

"Stateless" gets thrown around a lot, but the definition that actually matters is simple: a stateless system doesn't remember anything about previous requests. Every request is treated like the first one it's ever seen. If the system needs to know who you are or what you did a second ago, that information has to travel with the request, it isn't sitting in memory waiting for you.

The confusion usually comes from conflating "stateless" with "the app has no state at all," which isn't true. Almost every real app has state, logged-in users, shopping carts, workflow progress. The question isn't whether state exists, it's where it lives.

The Breakdown

Stateless vs. stateful, concretely:

  • Stateful — the server keeps context in memory between requests. A chat server holding a session object per connected user. A database holding an open transaction. Restart the process, and that in-flight context is gone.
  • Stateless — the server holds nothing between requests. Restart it mid-traffic and nothing is lost, because nothing was being held there in the first place.

Where this shows up in a typical Django + DRF stack:

  • REST APIs are stateless by design. Each HTTP request is expected to carry everything needed to process it auth token, params, whatever rather than relying on the server "remembering" the client from the last call.
  • Django's login sessions are a good example of state living outside the process. The app itself doesn't remember you. It stores a session ID in a cookie, and on every request it looks up the actual session data from a store, Postgres, Redis, cache that's separate from the running process. The stateless server is faking statefulness by outsourcing memory to something else.
  • Celery workers are stateless too. Each task carries its own payload. A worker doesn't need to recall the last ten tasks to execute the next one which is exactly why you can spin worker count up or down without coordination.

Why this matters for scaling:

This is the real payoff. If your app servers are stateless, any instance can handle any request, there's no "sticky" server that has to be the one you talk to because it remembers you. That's what makes horizontal scaling behind a load balancer straightforward: spin up a new instance on Railway or Koyeb, drop it into the pool, done. No user gets "stuck" to a dying instance.

The tradeoff is real, though: you're trading in-memory speed for a round trip to Redis or Postgres on every request that needs context. Statelessness buys resilience and scalability; it costs you a lookup.

The Reframe

Statelessness isn't about having no memory, it's about deciding where memory lives. Push it out of the process and into a shared store, and any server becomes disposable. That's the whole trick behind scaling horizontally without your app falling over every time you restart something.

More posts

Backend EngineeringJul 30, 20265 min read

Understanding the N+1 Query Problem in Django (Part 1)

Learn what the N+1 query problem is in Django, why it slows down your APIs, and how to eliminate unnecessary database queries using `select_related()` and `prefetch_related()`. This guide covers the fundamentals of Django ORM optimization with practical examples and best practices for building faster, more scalable applications.

Backend EngineeringJul 30, 20263 min read

Before You Scale: A Production Readiness Series

A comprehensive 20-part software engineering series covering production readiness, performance optimization, database tuning, API design, caching, Docker, CI/CD, monitoring, security, load testing, horizontal scaling, high availability, disaster recovery, and cost optimization. Learn how to build applications that are reliable, scalable, and ready for real-world traffic.