← All posts
Backend3 September 202611 min read

Putting Django behind the apps I already shipped

Owning the API turned out to be easier than owning the crash reports. A walk through the backend now serving this site.

I spent four years treating the backend as somebody else's problem. Then I needed an API that nobody else was going to build.

Why Django and not something lighter

I wanted the admin. Not a framework with an admin plugin — the real one, where a model gets a usable CRUD interface the moment you register it. For a one-person project that is the whole value proposition.

The layering that kept it clean

# apis.py  ->  selectors.py / services.py  ->  models.py
def post_list() -> QuerySet[Post]:
    return (
        Post.objects.filter(status=Post.Status.PUBLISHED)
        .select_related("category")
        .order_by("-published_at")
    )

Views never touch the ORM directly. Reads go through selectors, writes through services. It is more files, and it is worth it the first time a query needs changing in exactly one place.

What surprised me

select_related and prefetch_related are not optimisations you add later. Miss one on a list endpoint and you turn a single query into one per row. I shipped that bug once and caught it only because the page took a second to load.

What this site runs on

Django 5.2, DRF, Postgres, and the Unfold admin. It serves the posts, the app listings, and the profile you are reading right now.

Written by Sulton UzDev. Get new posts by email →

Sulton UzDev
Senior Android Developer · Kotlin, Compose & KMP · I build the app and its backend
© 2026 Sulton UzDevUzbekistanBlogProjectsAboutSubscribe