( Migration guide )

Migrating from NestJS to Python, step by step

You can move a NestJS backend to Python without changing how it is organised. Austial keeps the module, controller and provider structure and runs on FastAPI, so the port is mostly a translation of syntax and libraries rather than a redesign. This guide gives an order that works and flags what does not carry over.

A migration order that works

  • Scaffold the Python project with austial new. It gives you the root module, a health module and the test setup.
  • Port one module at a time, starting with modules that depend on nothing else. Generate each one with austial generate resource, then replace the placeholders.
  • Translate DTOs from class-validator classes to Pydantic models. The field types stay the same.
  • Keep providers as they are. Constructor injection stays, and the container reads your type hints instead of reflect-metadata.
  • Port guards, pipes and interceptors. The decorators and the request order are the same.
  • Move the data layer. The built-in ORM is TypeORM-shaped, so entities, repositories and the query builder map across. It supports PostgreSQL and SQLite today.
  • Port the tests with Test.create_testing_module, then run old and new side by side behind a proxy and move routes over as each module passes.

NestJS to Austial, task by task

NestJS to Austial, task by task
TaskNestJS (TypeScript)Austial (Python)
Create a projectnest new appaustial new app
Generate a featurenest g resource catsaustial g resource cats
Route with a parameter@Get(':id') with @Param('id')@Get(":id") with id: int in the handler
Read the body@Body() dto: CreateCatDtodto: CreateCatDto = Body()
Validate inputclass-validator decoratorsPydantic BaseModel fields
Inject a serviceconstructor(private cats: CatsService)def __init__(self, cats_service: CatsService)
Protect a route@UseGuards(AuthGuard)@UseGuards(AuthGuard)
Throw an HTTP errorthrow new NotFoundException()raise NotFoundException("...")
ConfigurationConfigModule and ConfigServiceConfigModule.for_root() and ConfigService
Test a moduleTest.createTestingModule()Test.create_testing_module()

Porting a controller, service and DTO

A typical NestJS cats module becomes this. The structure is the same: a DTO, an injectable service and a controller that receives the service in its constructor.

from austial import Body, Controller, Get, Injectable, NotFoundException, Post
from pydantic import BaseModel


class CreateCatDto(BaseModel):
    name: str
    age: int


@Injectable()
class CatsService:
    def __init__(self) -> None:
        self._cats: dict[int, dict] = {}

    def create(self, dto: CreateCatDto) -> dict:
        cat = {"id": len(self._cats) + 1, **dto.model_dump()}
        self._cats[cat["id"]] = cat
        return cat

    def find_one(self, id: int) -> dict:
        if id not in self._cats:
            raise NotFoundException(f"Cat #{id} not found")
        return self._cats[id]


@Controller("cats")
class CatsController:
    def __init__(self, cats_service: CatsService):
        self.cats_service = cats_service

    @Post()
    async def create(self, dto: CreateCatDto = Body()) -> dict:
        return self.cats_service.create(dto)

    @Get(":id")
    async def find_one(self, id: int) -> dict:
        return self.cats_service.find_one(id)

What does not carry over

  • File names use underscores (cats_controller.py), because Python cannot import a file called cats.controller.py.
  • Request data uses marker defaults such as Body(), Query() and Param() instead of parameter decorators.
  • Interceptors wrap the handler with a plain async continuation, not an RxJS stream.
  • The HTTP platform is FastAPI only. There is no Express or Fastify adapter layer.
  • GraphQL is code-first through Strawberry. There is no schema-first mode.
  • The built-in ORM supports PostgreSQL and SQLite, and there is no adapter for TypeORM, Sequelize or MikroORM.

Frequently asked questions

Do I have to redesign my architecture to move from NestJS to Python?

No. Austial keeps NestJS's module, controller and provider structure and its request pipeline, so the architecture carries over. What changes is the language, the validation library and the data layer.

Can I migrate a NestJS app gradually?

Yes. Port one module at a time, starting with modules that have no dependencies, and run the old and new services side by side behind a proxy until each module passes its tests.

Will my API documentation still work?

Yes. Austial runs on FastAPI, which generates an OpenAPI schema at /openapi.json and serves interactive docs at /docs.

Last updated

Go deeper in the docs

( Keep reading )

( Click. Copy. Build. )

Seeing “command not found”? Run uv tool update-shell, then open a new terminal. Details