# Scaling Nextdoor’s Datastores: Part 1

[Nextdoor](https://yomu.fyi/company/nextdoor) · Slava Markeyev · Mar 19, 2025

**Type:** Explainer

## Summary

Nextdoor relies on a Django backend connected to monolithic PostgreSQL databases and Redis look-aside caches. Migrating to distributed SQL datastores proved impractical because legacy business logic depends heavily on multi-table joins that could not be rewritten. Intermediate mitigations, including read replicas and data partitioning by severing foreign keys, extended infrastructure runways but left primary databases vulnerable to load bottlenecks. Furthermore, look-aside caching and replica usage introduced data staleness risks, atomicity losses across partitioned databases, and inconsistent cache-population behaviors. To address these limitations, Nextdoor initiated an architecture redesign focused on dynamic query routing to replicas, replica-driven cache hydration, time-bounded eventual consistency, and schema-resilient cache serialization.

## Context

Nextdoor's Django backend relies heavily on relational PostgreSQL data models with complex multi-table joins. Transitioning to distributed SQL was infeasible due to widespread legacy queries that a small team could not rewrite without halting product development. Over time, primary databases remained bottlenecks and single points of failure despite using Redis look-aside caches, read replicas, and partitioned databases.

## Approach / What changed

Nextdoor evaluated the limits of their existing mitigations—severed foreign keys, look-aside caching, and read replicas—and initiated an architecture redesign. Their goals include dynamically routing read queries to replicas, populating caches directly from read replicas, guaranteeing time-bounded eventual cache consistency, and maintaining cache compatibility across schema modifications.

## Takeaways

- Adopting distributed SQL datastores can be blocked when entrenched application codebases rely heavily on multi-table joins across monolithic relational models.
- Partitioning databases by severing foreign-key relationships extends scaling runway but can subtly break transactional atomicity during successive writes across databases.
- Querying the primary database during a cache miss does not guarantee that the value written to the cache reflects the most up-to-date data.

**Tags:** [Caching](https://yomu.fyi/topic/caching), [Postgres](https://yomu.fyi/topic/postgres), [Python](https://yomu.fyi/topic/python), [Redis](https://yomu.fyi/topic/redis), [Scalability](https://yomu.fyi/topic/scalability)

[Read original post](https://engblog.nextdoor.com/scaling-nextdoors-datastores-part-1-234d0cf67665)
