Run Django on CockroachDB

Run Django on CockroachDB with the django-cockroachdb backend: match backend and Django versions, configure TLS connections, handle transaction retries, adjust migrations and primary keys, and understand what works differently from PostgreSQL.

Problem statement

You need a database that survives the loss of a node, zone, or region without manual failover, or that serves users in several regions with local reads. CockroachDB is a distributed SQL database that speaks the PostgreSQL wire protocol. Django can use it through the django-cockroachdb backend, but it is not a drop-in PostgreSQL: transactions are serializable and may need retries, some PostgreSQL features are missing or different, and schema changes run online in the background.

Django on CockroachDBdjango-cockroachdbbackendTLS connectionport 26257Serializable txnsretry on 40001Distributed rangessurvive node lossWire-compatible with PostgreSQL, but with serializable transactions that may need retries.
  1. Install django-cockroachdb matching your Django version, and set ENGINE = "django_cockroachdb".
  2. Connect over TLS to port 26257 (CockroachDB Cloud provides a connection string and CA certificate).
  3. Expect serialization errors (SQLSTATE 40001) under contention and retry whole transactions.
  4. Prefer UUID primary keys or accept CockroachDB's unique_rowid() behavior for integer keys.
  5. Test your migrations and queries against CockroachDB in CI; some PostgreSQL-specific features are unsupported.

Step-by-step solution

1. Install and configure the backend

pip install django-cockroachdb psycopg[binary]
DATABASES = {
    "default": {
        "ENGINE": "django_cockroachdb",
        "NAME": "shop",
        "USER": "shopapp",
        "PASSWORD": os.environ["DB_PASSWORD"],
        "HOST": "shop-cluster.aws-eu-central-1.cockroachlabs.cloud",
        "PORT": "26257",
        "OPTIONS": {"sslmode": "verify-full", "sslrootcert": "/etc/ssl/crdb/root.crt"},
        "CONN_MAX_AGE": 60,
    }
}

The backend's major version follows Django's (for example, django-cockroachdb 5.2.x for Django 5.2). Using mismatched versions causes errors at startup.

2. Handle transaction retries

CockroachDB runs transactions at SERIALIZABLE isolation. When concurrent transactions conflict, one fails with:

psycopg.errors.SerializationFailure: restart transaction: TransactionRetryWithProtoRefreshError

Retry the whole unit of work:

import time
from django.db import OperationalError, transaction

def run_in_txn(fn, attempts=5):
    for i in range(attempts):
        try:
            with transaction.atomic():
                return fn()
        except OperationalError as exc:
            if getattr(exc.__cause__, "sqlstate", None) != "40001" or i == attempts - 1:
                raise
            time.sleep(0.05 * 2 ** i)

Keep transactions short and avoid hot rows (counters updated by every request), which cause the most retries.

differences that affect Django codeCockroachDBPostgreSQLIsolation!serializable, retriesread committedInteger IDsunique, not orderedsequencesSchema changesonline, asynclocking DDLExtensions!fewmanyFailoverautomaticneeds HA setupResilience comes with stricter transactions and fewer featuresdjango-deployment.com
Code that never retries transactions needs changes before moving to CockroachDB.

3. Primary keys and ordering

Integer AutoField columns use unique_rowid() (or identity columns, depending on settings), producing large, non-sequential values. Code that assumes IDs reflect insertion order breaks; order by a timestamp instead. Sequential keys also concentrate writes on one range; UUID primary keys spread them:

import uuid
class Order(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

4. Migrations and schema changes

Schema changes in CockroachDB run as background jobs while the table stays available. Django migrations work, but DDL inside a transaction with other statements has limitations; the backend handles common cases. Some operations behave differently, such as altering column types. Run the full migration history against CockroachDB in CI before switching.

5. Know the unsupported features

Check the backend's documentation for its current list. Typical gaps include some PostgreSQL extensions, full-text search features (django.contrib.postgres.search lookups behave differently or are unsupported), and certain index types. Test the parts of django.contrib.postgres you rely on.

do you need distributed SQL?What problem are you solving?survive zone or region lossCockroachDBautomatic failoverusers in several regionsCockroachDBregional tablessingle region, speedPostgreSQLwith HA replicaFor most single-region apps, managed PostgreSQL is simpler and fasterdjango-deployment.com
Distributed consensus adds latency to writes compared with a local PostgreSQL.

Explanation

CockroachDB splits data into ranges replicated with the Raft consensus protocol across nodes. Every write needs agreement from a majority of replicas, which is what lets the cluster survive failures without losing committed data. To keep that correct under concurrency, it uses serializable isolation and resolves conflicts by asking clients to retry. Django's PostgreSQL-based backend works with these semantics once retries are handled and PostgreSQL-only features are avoided.

Edge cases / notes

  • Latency. Writes involve a consensus round; multi-region writes can take tens of milliseconds more than local PostgreSQL.
  • Connection pooling. Connections are cheaper than in PostgreSQL, but pooling still helps with many workers.
  • Licensing. CockroachDB's licensing has changed over time; check the current terms for self-hosted clusters.

Next steps

FAQ

Does Django support CockroachDB?

Through the third-party django-cockroachdb backend, maintained to track Django releases.

Can I use the standard PostgreSQL backend?

Not reliably. Use the dedicated backend, which handles CockroachDB's differences.

Why do I get serialization errors?

Concurrent transactions conflicted under serializable isolation. Retry the whole transaction.

Are auto-increment IDs sequential on CockroachDB?

No. They are unique but not sequential. Order records by timestamps.

Keep going