Articles

15 essays, newest first

2026

  1. Decomposing hardcoded roles: rewriting access control in a Django app without breaking customers

    How we replaced three hardcoded roles with 46 named permissions and customer-defined roles, and proved nothing changed before changing anything.

    8 min read

  2. Migrating a production Django app from Elasticsearch to OpenSearch

    How a one-line urllib3 security bump turned into migrating a Django app from elasticsearch-py to opensearch-py, and what we vendored to keep the API responses unchanged.

    8 min read

  3. Almost done: the hidden tradeoffs of Playwright E2E testing in a fast-moving app

    A week of investigating Playwright on a fast-moving UI ended with a recommendation to stop. Four hidden costs that make end-to-end tests cheap to start and expensive to keep.

    5 min read

  4. How I added project-aware tab completion to Django's manage.py

    Django's bundled bash completion only knows command names and flags. django-completion adds app labels and migration names by reading a JSON cache that is rebuilt after each manage.py command, so Tab never loads Django.

    3 min read

  5. From Django library to AWS Cognito: my journey building enterprise SSO

    How a multi-provider SSO requirement took me from rewriting a Django SSO library to an AWS Cognito setup where adding a new identity provider needs no server code changes.

    6 min read · Enterprise SSO with Django and AWS Cognito, part 6 of 6

  6. How to set up SSO authentication in your app's admin panel

    How to configure SSO account and notification settings in a Django admin panel backed by AWS Cognito, automate the setup through an admin API, and trigger user soft-deletes from Azure and Okta.

    8 min read · Enterprise SSO with Django and AWS Cognito, part 5 of 6

  7. How to test SSO authentication with Cognito and OIDC providers

    How to test SSO login and logout through AWS Cognito with an external OIDC provider, check that the user was created, and what a failed group validation looks like.

    3 min read · Enterprise SSO with Django and AWS Cognito, part 4 of 6

  8. How to configure AWS Cognito for SSO: a step-by-step guide

    How to set up AWS Cognito for multi-tenant SSO: an app client per customer, a custom groups attribute, external OIDC providers, and a managed login page.

    3 min read · Enterprise SSO with Django and AWS Cognito, part 3 of 6

  9. Okta single sign-on (SSO) setup: a step-by-step guide

    How to set up an Okta OIDC application for SSO: groups, role attributes, scopes, claims, access policies, event hooks for soft-deleting users, and optional MFA.

    12 min read · Enterprise SSO with Django and AWS Cognito, part 2 of 6

  10. Azure single sign-on (SSO) setup: a step-by-step guide

    How to register an app in Azure (Microsoft Entra ID) for OIDC SSO: scopes, group claims, API permissions, app roles, groups, user soft-deletion, and optional MFA.

    11 min read · Enterprise SSO with Django and AWS Cognito, part 1 of 6

2025

  1. Django without the mess: repositories for data, services for rules

    Why selectors are a trap for cleaning up fat Django models, and how repositories for data access plus services for business rules keep the layers apart.

    7 min read

  2. Django REST Framework: when (and when not) to override serializers and viewsets, part 2

    Part 2 covers ViewSets: when to override create versus perform_create, how update, partial_update, and perform_update fit together, and a cheat sheet for where each kind of logic goes.

    6 min read · Django REST Framework overrides, part 2 of 2

  3. Django REST Framework: when (and when not) to override serializers and viewsets, part 1

    Part 1 covers serializers: which methods to override for validation, saving, and output formatting, and what logic does not belong in a serializer at all.

    4 min read · Django REST Framework overrides, part 1 of 2

  4. Why Django REST Framework doesn't show your custom validation error messages (and what to do about it)

    DRF validates at the serializer level and skips model full_clean(), so custom messages on model constraints never reach the API response. Three ways to work around it.

    2 min read

  5. Boost your Django Docker images by using uv package and project manager

    A multi-stage Dockerfile for Django that installs dependencies with uv, uses cache mounts for faster rebuilds, and works around a .venv permission issue. In my project the build went from 34.6s to 15.8s.

    4 min read