Hi everyone,
I wanted to share a project I’ve been working on to make Postgres Row-Level Security (RLS) easier and more maintainable in Django projects.
Background
Postgres RLS is a powerful feature for isolating tenant or user data at the database level, but integrating it smoothly with Django isn’t always straightforward:
- You often end up scattering raw SQL across migrations and setup scripts.
- It’s tricky to keep policies and models in sync over time.
- The logic can become opaque for teams who haven’t worked with RLS before.
What is django-rls?
django-rls is an open-source package that lets you:
Define RLS policies declaratively right alongside your Django models
Auto-generate migrations that create and update policies in Postgres
Attach policies dynamically to different database roles (e.g., tenant users, admins)
Keep your tenant isolation logic explicit, version-controlled, and testable
Quick Example
Here’s a minimal example of defining a policy on a model:
from django_rls.models import RLSModel, RLSPolicy
class Invoice(RLSModel):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=10, decimal_places=2)
class RLS:
policies = [
RLSPolicy(
name="tenant_isolation",
using="customer_id = current_setting('myapp.tenant_id')::integer"
)
]
When you run makemigrations
, django-rls will generate the SQL to create or update this policy in Postgres automatically.
Why you might care
If you’re building SaaS applications with multi-tenancy or any scenario where you want to lock down access at the DB layer, RLS can be a strong line of defense. The goal of django-rls is to make this feel as natural as defining Meta
options on a model.
Project & Links
Website: django-rls.com
Docs: django-rls.com/docs
GitHub: github.com/kdpisda/django-rls
Looking for Feedback
I’d love to hear:
- If you’ve tried RLS before, what challenges you faced?
- Any features or integrations you’d find valuable?
- Suggestions for improvements or edge cases I might have missed.
Thanks for reading—and I hope this helps make RLS more approachable in Django projects. Happy to answer any questions!