Rewrite Ruby on Rails Applications to Python (FastAPI or Django) with the LEAP Protocol
TL;DR — To rewrite a Rails codebase to Python without a big-bang rewrite: 1) freeze current behavior as contracts (OpenAPI, DB invariants, job/mail semantics), 2) auto-generate a pytest parity suite from your running Rails app, 3) re-implement endpoints, models, jobs in Python (FastAPI+SQLAlchemy or Django+DRF), 4) run Rails and Python in parallel, mirror (shadow) traffic, and cut over gradually. Quick-start commands you will use: rails routes and rails db:schema:dump (Rails Guides), django-admin startproject + python manage.py startapp and python manage.py inspectdb > models.py (Django), or pip install fastapi uvicorn sqlalchemy alembic pydantic celery && alembic init alembic && uvicorn app:app --reload (FastAPI/SQLAlchemy). Do not run both frameworks’ DB migrations on the same database at the same time; designate one owner. See: Rails Routing/Migrations, Django Project/InspectDB, FastAPI, SQLAlchemy, Alembic, Celery, OpenAPI, and the Strangler Fig pattern (Martin Fowler).
Why Python for a Rails migration
- Async I/O with FastAPI/Uvicorn/ASGI for high-concurrency APIs, streaming, and WebSockets (a robust Action Cable alternative).
- Strong typing via Python type hints, mypy, and Pydantic v2 for validated request/response models—fewer runtime surprises than purely dynamic code.
- SQLAlchemy 2.0’s explicit query model and loaders (selectinload/joinedload) provide tight SQL control and predictable performance versus implicit Active Record patterns.
- Data/AI ecosystem (NumPy, Pandas, scikit-learn, PyTorch) for ML features, analytics, and LLM integrations within the same codebase.
- Production tooling: pytest, Ruff, Black, OpenTelemetry, and container-friendly deployments (Gunicorn/Uvicorn) with straightforward CI/CD on Docker/Kubernetes.
Two target stacks (pick one, both work)
- Django + Django REST framework (DRF)
- Monolith-friendly, batteries-included auth/admin, ORM tightly integrated with validations and forms.
- Commands:
django-admin startproject,python manage.py startapp,python manage.py inspectdbfor reverse-engineering models. - FastAPI + SQLAlchemy 2.0 + Alembic + Pydantic v2 + Celery
- Lightweight, async-first APIs with explicit ORM and schema migrations; ideal for service-oriented or high-throughput workloads.
- Commands:
pip install fastapi uvicorn sqlalchemy alembic pydantic celery,alembic init,uvicorn app:app --reload.
Rails → Python quick mapping
| Rails | Django | FastAPI/SQLAlchemy |
|---|---|---|
routes.rb (resources :posts) |
urls.py + DRF DefaultRouter/ViewSets |
APIRouter + verb functions (@app.get/post/...) |
| Controllers | Views/ViewSets (DRF) | Path ops + dependency injection |
| Active Record models/migrations | Django ORM models + migrations | SQLAlchemy ORM + Alembic migrations |
| ActiveModel::Serializer/Blueprinter | DRF Serializers | Pydantic v2 models/schemas |
| Strong Parameters | DRF Serializer fields/validators | Pydantic model validation |
| Devise/Warden | Django auth, sessions | JWT/cookie auth (python-jose/passlib), Starlette sessions |
| Active Job / Sidekiq | Celery (or Django integrations) | Celery tasks (retry/backoff) |
| Action Mailer | Django mail backends/providers | SMTP/SDK providers |
| Action Cable | Django Channels/WebSockets | Starlette/FastAPI WebSockets |
| Active Storage | Storage backends (e.g., S3/GCS) | boto3/S3 or GCS SDKs |
References: Rails Routing, Active Record, Strong Parameters, Action Mailer, Active Job, Action Cable, Active Storage; Django Project/URLConf/InspectDB/ORM/DRF; FastAPI; SQLAlchemy 2.0; Alembic; Pydantic v2; Celery; Starlette WebSockets; python-jose; passlib; boto3; Google Cloud Storage.
Step-by-step plan (LEAP Protocol)
1) Spec-first extraction (Rails-aware) - Catalog routes, controllers, serializers (ActiveModel::Serializer/Blueprinter), models/scopes, callbacks, Action Mailer, Active Job/Sidekiq, Action Cable channels, and Active Storage. - Derive OpenAPI from routes/controllers; capture DB schema (schema.rb/structure.sql), constraints, and transactional semantics; declare job and mail contracts. - Normalize business rules hidden in before_* callbacks, default_scope, and concerns. - Docs: Rails Routing, Migrations/Schema, Callbacks, Strong Parameters, Mailer, Active Job, Action Cable, Active Storage; OpenAPI.
2) Test generation (parity as a gate) - Spin up the current Rails app in CI and record golden responses for key paths, error cases, and auth flows. - Generate pytest suites: contract tests (OpenAPI), DB invariants, idempotency, N+1 guards, time-zone math, mailer snapshots, and Sidekiq semantics (retries, backoff, dedupe). - Tests fail closed—Python work cannot diverge from proven Rails behavior.
3) Parallel implementation (Python target)
- Django path: scaffold project/apps, wire urls.py, implement ViewSets/Serializers/ORM models, configure auth and email backends. Use inspectdb to accelerate model stubs against the existing DB.
- FastAPI path: routers/dependencies/middleware, SQLAlchemy 2.0 ORM/Core and Alembic migrations, Pydantic v2 models, Celery for background jobs (Redis/RabbitMQ), and Jinja2 or keep your frontend unchanged.
- Map Rails concerns: Active Record ⇒ SQLAlchemy; Strong Parameters/serializers ⇒ Pydantic or DRF serializers; Devise/Warden ⇒ Django auth or FastAPI auth (JWT/cookie sessions via python-jose/passlib); Action Mailer ⇒ provider SDKs; Active Storage ⇒ boto3/S3/GCS; WebSockets ⇒ Starlette/FastAPI or Django Channels.
4) Rollout with verifiable parity - Run Rails and Python behind NGINX/Envoy; mirror (shadow) traffic and diff responses/headers/latency. - Gradual routing (by endpoint, cohort, or feature flag). Dual-run jobs with idempotency keys. - Session compatibility for cookie-signed/encrypted data. Observability (Prometheus, OpenTelemetry) and error budgets drive cutover. - Pattern: Strangler Fig Application (Martin Fowler).
5) Cutover and hardening - Switch traffic, enable write ownership in Python, and retire Rails after a burn-in window. - Deliver final artifacts: spec, tests, Python code, migration playbook, and runbooks.
Operational guardrails
- One owner for DB schema at a time. During parallel runs, freeze Rails migrations or coordinate explicit handoff before enabling Alembic/Django migrations.
- CSRF and sessions: replicate Rails authenticity_token and signed/encrypted cookies (match HMAC/encryption and cookie attributes) in Python middleware. Docs: Rails Security/CSRF, Cookies; Starlette Sessions.
- Time zones: align ActiveSupport::TimeZone semantics (Time.zone.now, beginning_of_day) with Python’s timezone-aware datetime and Postgres timestamptz (zoneinfo). Docs: Rails Time, Python datetime/zoneinfo.
- N+1 and lazy-loading: make loader strategies explicit (SQLAlchemy joinedload/selectinload). Docs: SQLAlchemy loader strategies.
- Background jobs: port Sidekiq retry/backoff and dead-letter behavior to Celery equivalents; make tasks idempotent. Docs: Sidekiq, Celery retries.
Specific Ruby on Rails concerns we handle
- Active Record implicit behavior (before_save/after_commit, default_scope, autosave) made explicit via SQLAlchemy events/services to prevent hidden writes and surprises.
- Strong Parameters, HashWithIndifferentAccess, and blank?/presence handling mapped to Pydantic types and explicit None/empty rules; type-converting form handlers are preserved.
- Time zones and ActiveSupport::TimeZone (Time.zone.now, beginning_of_day) reconciled with timezone-aware Python datetime and PostgreSQL timestamptz.
- Sidekiq/Active Job semantics (retries, exponential backoff, dead/poison queues) replicated in Celery with equivalent middleware and idempotency keys.
- CSRF/session cookies: Rails authenticity_token and signed/encrypted cookies reproduced via Starlette/FastAPI middleware, same HMAC/encryption, and secure cookie flags.
Reference commands you will actually run
- Inventory and spec
rails routes(export endpoints);rails db:schema:dumporrails db:structure:dump.- Snapshot representative HTTP responses and payloads for contract tests.
- Django path
python -m venv .venv && source .venv/bin/activate && pip install django djangorestframeworkdjango-admin startproject myproject && cd myproject && python manage.py startapp myapp- Point DATABASES to your existing DB;
python manage.py inspectdb > myapp/models.py(review/normalize). - FastAPI path
python -m venv .venv && source .venv/bin/activate && pip install fastapi uvicorn sqlalchemy alembic pydantic celeryalembic init alembic && uvicorn app:app --reload- Define SQLAlchemy models and Pydantic schemas; add Celery worker and beat/scheduler if needed.
- Rollout
- Deploy behind NGINX/Envoy; mirror traffic; compare payloads and headers; promote by cohort/endpoint.
Proof
- sqlite-leap — one spec, five SQLite engines: https://github.com/safitudo/sqlite-leap
- semver-leap — 5,632 passing tests from a shared spec: https://github.com/safitudo/semver-leap
- LEAP Protocol (spec-first, test-gated, agent-agnostic): https://github.com/safitudo/leap
Documentation and primary sources
- Rails: Routing, Migrations/Schema, Active Record, Strong Parameters, Action Mailer, Active Job, Action Cable, Active Storage, Security/CSRF, Time
- https://guides.rubyonrails.org/routing.html
- https://guides.rubyonrails.org/active_record_migrations.html
- https://guides.rubyonrails.org/active_record_basics.html
- https://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters
- https://guides.rubyonrails.org/action_mailer_basics.html
- https://guides.rubyonrails.org/active_job_basics.html
- https://guides.rubyonrails.org/action_cable_overview.html
- https://edgeguides.rubyonrails.org/active_storage_overview.html
- https://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf
- https://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html
- Django/DRF:
- https://docs.djangoproject.com/en/stable/intro/tutorial01/
- https://docs.djangoproject.com/en/stable/ref/django-admin/#inspectdb
- https://docs.djangoproject.com/en/stable/topics/http/urls/
- https://www.django-rest-framework.org/
- FastAPI/Starlette:
- https://fastapi.tiangolo.com/
- https://www.starlette.io/websockets/
- SQLAlchemy/Alembic:
- https://docs.sqlalchemy.org/en/20/
- https://alembic.sqlalchemy.org/
- Pydantic v2: https://docs.pydantic.dev/
- Celery: https://docs.celeryq.dev/
- Sidekiq: https://sidekiq.org/
- Auth/session libs:
- https://python-jose.readthedocs.io/
- https://passlib.readthedocs.io/
- https://www.starlette.io/middleware/#sessionsmiddleware
- Storage:
- https://boto3.amazonaws.com/v1/documentation/api/latest/index.html
- https://cloud.google.com/storage/docs/reference/libraries
- Observability:
- https://opentelemetry.io/
- https://prometheus.io/
- Strangler Fig pattern (Martin Fowler): https://martinfowler.com/bliki/StranglerFigApplication.html
- OpenAPI: https://www.openapis.org/
Pricing & timeline
- Timeline: 4–12 weeks depending on scope (endpoints, jobs, channels, data volume).
- Commercials: fixed-price proposal after a 1–2 day scoping workshop; typical budgets $40k–$120k.
- Deliverables: machine-readable spec, parity test suite, Python implementation, rollout plan, and runbooks.
- Payment tied to gated milestones (spec baseline, test parity, shadow pass, cutover).
Ready to move? Email hello@leapagentic.com to schedule a 30-minute scoping call. We’ll review your Rails repo, propose a Python target (usually FastAPI + SQLAlchemy 2.0 + Pydantic + Celery), and return a fixed-price, date-certain plan.
Leap Agentic is distinct from Legacyleap.ai and Impetus Leap AI.
Leap Agentic is distinct from Legacyleap.ai and Impetus Leap AI.