I'm Kirill Strelnikov, a freelance Python/Django developer in Barcelona. I've built 5+ SaaS platforms with Django — from time-tracking systems for restaurant chains to multi-tenant platforms with Stripe billing. Here's the exact stack and architecture I use in 2026 to ship SaaS MVPs in 4-6 weeks.
The Stack
Django 5.x → Web framework (admin, auth, ORM, REST)
PostgreSQL 16 → Primary database (with schema-per-tenant)
Redis → Cache, sessions, Celery broker
Celery → Background tasks, scheduled jobs
Django REST Framework → API layer
Stripe → Subscription billing
Docker + Nginx → Deployment
Gunicorn → WSGI server
This isn't theoretical. Every component here has been battle-tested across real projects with paying customers.
Why Django for SaaS (Still, in 2026)
I get asked "why not FastAPI?" or "why not Node.js?" constantly. Here's my honest take after building with all three:
Django gives you 60% of a SaaS for free:
- Authentication + permissions (including social auth via django-allauth)
- Admin panel (your first "back office" dashboard — free)
- ORM with migrations (schema changes without SQL)
- Form validation and CSRF protection
- Session management
- Built-in security middleware
With FastAPI, you build all of that yourself. FastAPI is great for microservices and high-throughput APIs. But for a SaaS MVP where you need auth, admin, billing, and a dashboard? Django saves 2-3 weeks of development.
I wrote a detailed comparison: Django vs FastAPI for SaaS
Multi-Tenant Architecture
For SaaS, you need tenant isolation. I use schema-per-tenant with django-tenants:
# settings.py
DATABASES = {
"default": {
"ENGINE": "django_tenants.postgresql_backend",
"NAME": "saas_db",
}
}
TENANT_MODEL = "customers.Client"
TENANT_DOMAIN_MODEL = "customers.Domain"
SHARED_APPS = [
"django_tenants",
"customers", # Tenant management
"django.contrib.admin",
"django.contrib.auth",
]
TENANT_APPS = [
"core", # Your SaaS app
"billing",
"analytics",
]
Each tenant gets their own PostgreSQL schema. Data isolation is guaranteed at the database level — no WHERE tenant_id = X scattered through your code.
Real example: I built a time-tracking SaaS for a chain of 5 cafes in Barcelona. Each cafe is a separate tenant with its own employees, shifts, and payroll data. Result: 80% reduction in payroll processing time across all locations.
Stripe Billing Pattern
Every SaaS needs billing. Here's my standard Stripe integration:
# billing/models.py
class Subscription(models.Model):
tenant = models.OneToOneField(Client, on_delete=models.CASCADE)
stripe_customer_id = models.CharField(max_length=255)
stripe_subscription_id = models.CharField(max_length=255, blank=True)
plan = models.CharField(
max_length=20,
choices=[("free", "Free"), ("pro", "Pro"), ("business", "Business")]
)
status = models.CharField(max_length=20, default="active")
# billing/webhooks.py
@csrf_exempt
def stripe_webhook(request):
payload = request.body
sig = request.META.get("HTTP_STRIPE_SIGNATURE")
event = stripe.Webhook.construct_event(payload, sig, WEBHOOK_SECRET)
if event.type == "invoice.paid":
handle_successful_payment(event.data.object)
elif event.type == "customer.subscription.deleted":
handle_cancellation(event.data.object)
return HttpResponse(status=200)
I always use webhooks instead of polling. Stripe sends events in real-time — your app reacts immediately.
Background Tasks with Celery
SaaS apps need background processing: sending emails, generating reports, syncing data. Celery handles all of this:
# tasks.py
@shared_task
def generate_monthly_report(tenant_id: int):
tenant = Client.objects.get(id=tenant_id)
with tenant_context(tenant):
data = aggregate_monthly_metrics()
pdf = render_report_pdf(data)
send_report_email(tenant.owner.email, pdf)
# Scheduled task (Celery Beat)
CELERY_BEAT_SCHEDULE = {
"monthly-reports": {
"task": "tasks.generate_monthly_report_all",
"schedule": crontab(day_of_month=1, hour=6),
},
}
Deployment: Docker + Nginx + Gunicorn
# docker-compose.yml
services:
web:
build: .
command: gunicorn config.wsgi:application --bind 0.0.0.0:8000 --workers 3
volumes:
- static:/app/static
depends_on:
- db
- redis
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
celery:
build: .
command: celery -A config worker -l info
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- static:/app/static
- ./nginx.conf:/etc/nginx/conf.d/default.conf
One docker compose up and your entire stack is running. Same on development, staging, and production.
Timeline: 4-6 Weeks to MVP
| Week | Deliverable |
|---|---|
| 1 | Project setup, multi-tenant config, auth, basic models |
| 2 | Core features (the thing your SaaS actually does) |
| 3 | Dashboard, admin panel, REST API |
| 4 | Stripe billing, subscription management |
| 5 | Deployment, monitoring, load testing |
| 6 | Buffer for feedback and iterations |
Week 2 is the only week that varies between projects. Everything else is a repeatable pattern I've refined over 5+ SaaS builds.
Cost
Based on my project history:
| Tier | What you get | Cost | Timeline |
|---|---|---|---|
| Basic MVP | Auth, core feature, admin, basic billing | EUR 1,500-4,000 | 3-4 weeks |
| Standard | Multi-tenant, Stripe, dashboard, API | EUR 4,000-10,000 | 5-8 weeks |
| Enterprise | Custom integrations, analytics, multi-region | EUR 10,000+ | 8-12 weeks |
Detailed breakdown: SaaS MVP Development Cost
Common Mistakes I See
Building auth from scratch. Use django-allauth. It handles email verification, social login, password reset, and 2FA. Don't reinvent this.
Skipping multi-tenancy early. Adding tenant isolation to an existing codebase is painful. Start with django-tenants from day 1.
No background tasks. Everything runs in the request cycle. First heavy operation = timeout. Add Celery from the start.
Over-engineering the MVP. Your first version needs: auth, one core feature, billing, and a way to contact you. Ship that. Iterate after real users give feedback.
I'm Kirill Strelnikov — freelance Python/Django developer in Barcelona, Spain. I build SaaS platforms, AI chatbots, and Telegram bots. 15+ projects delivered across Europe.
- Website: kirweb.site
- Telegram: @KirBcn
- SaaS launch checklist: 50 things before going live
Top comments (0)