FastAPI ganhou espaço muito rápido no ecossistema Python. É difícil não se empolgar: tipagem forte, performance excelente, documentação automática e uma curva de aprendizado que, à primeira vista, parece suave. Justamente aí mora o perigo.
O problema não é FastAPI. O problema é que ele funciona bem mesmo quando usado de forma errada. E isso engana. Muita coisa “parece ok” no começo, mas cobra a conta quando o projeto cresce, quando entra mais gente no time ou quando o código precisa sobreviver a refatorações reais.
Neste texto, quero falar menos de teoria e mais de erros práticos, daqueles que eu vejo repetidamente em projetos de iniciantes — e que eu mesmo já cometi.
Quando alguém começa com FastAPI, normalmente cria um main.py, define uma ou duas rotas, vê o Swagger funcionando e pensa: “pronto, minha API está feita”. O problema é que essa sensação de simplicidade faz muita gente cair na armadilha de centralizar absolutamente tudo em um único arquivo.
No início, colocar rotas, regras de negócio, acesso ao banco, validações e até código de autenticação no mesmo lugar parece produtivo. Você resolve rápido, enxerga tudo em um arquivo só e sente que está avançando. O problema é que esse tipo de organização não cresce. Em pouco tempo, o main.py vira um arquivo enorme, difícil de ler, difícil de testar e perigoso de modificar. Qualquer mudança passa a ter efeitos colaterais imprevisíveis.
FastAPI não exige modularização, mas foi claramente desenhado para ela. Ignorar isso é lutar contra o framework em vez de usá-lo a seu favor.
Outro erro muito comum é transformar a rota em um “Deus do sistema”. Vejo muitos códigos onde a função da rota recebe a requisição, valida dados, acessa o banco, aplica regra de negócio, decide status, monta resposta e, às vezes, até chama serviços externos. Tudo ali, na mesma função.
O problema não é só estético. Quando a lógica de negócio fica presa à camada HTTP, você perde flexibilidade. Fica difícil testar sem subir a API inteira. Fica difícil reutilizar a mesma regra em outro contexto. Fica difícil até entender o que a rota realmente faz, porque ela deixa de ser um ponto de entrada e vira o centro do sistema.
Na prática, a rota deveria ser apenas um orquestrador: recebe a requisição, chama a regra de negócio correta e devolve a resposta. A inteligência do sistema precisa viver fora dela. Quando essa separação não existe, o projeto até funciona, mas se torna frágil e caro de manter.
Um ponto que muita gente subestima no FastAPI é a tipagem. Por ser Python, alguns iniciantes ignoram completamente os tipos, usam dict para tudo e deixam o Pydantic apenas como um detalhe para gerar Swagger. Isso é um desperdício enorme.
A tipagem em FastAPI não é um luxo nem um excesso de formalismo. Ela é parte do mecanismo de segurança da aplicação. Quando você define schemas corretamente, você ganha validação automática, documentação clara, contratos explícitos entre API e consumidor e uma camada extra de proteção contra dados inválidos entrando no sistema.
Ignorar isso transforma FastAPI em algo muito próximo de um Flask mal organizado — só que com mais recursos desperdiçados.
Relacionado a isso, existe um erro ainda mais sutil: usar o mesmo modelo para tudo. O mesmo objeto que representa a tabela no banco passa a ser usado como entrada da API, saída da API e, às vezes, até como objeto interno de negócio.
No começo parece prático. Com o tempo, vira um problema sério. Você começa a expor campos que não deveria, tem dificuldade de alterar uma regra sem quebrar contratos antigos e cria um acoplamento forte entre camadas que deveriam ser independentes.
Separar modelos de banco de schemas de API não é burocracia. É uma forma de dizer claramente: “isso entra”, “isso sai” e “isso fica só dentro do sistema”. Quando essa distinção não existe, a API perde controle sobre o próprio formato de dados.
Outro erro clássico aparece no gerenciamento de dependências, especialmente conexão com banco de dados. É muito comum ver conexões globais, sessões abertas fora de contexto ou objetos compartilhados sem controle de ciclo de vida. Em aplicações simples isso até passa despercebido, mas em ambientes concorrentes os problemas aparecem rápido: conexões que não fecham, comportamento inconsistente, erros difíceis de reproduzir.
FastAPI oferece um sistema de dependências extremamente poderoso. Não usar Depends corretamente é abrir mão de um dos maiores diferenciais do framework. Quando as dependências são bem definidas, o código fica mais limpo, mais seguro e muito mais testável.
E falando em testes, talvez o erro mais recorrente — e mais caro — seja deixar isso para depois. Muitos iniciantes até sabem que deveriam testar, mas preferem “entregar logo” e prometem voltar nos testes quando o projeto estiver mais maduro. Essa maturidade quase nunca chega.
Sem testes, qualquer refatoração vira um risco. Sem testes, bugs chegam em produção. Sem testes, o medo de mexer no código cresce junto com o projeto. FastAPI, por ser tipado e modular, é excelente para testes unitários e de integração. Ignorar isso é desperdiçar uma vantagem estratégica.
Tudo isso converge para um problema central: falta de estrutura. Não pensar na organização de pastas desde o início é um erro que não aparece no primeiro commit, mas explode meses depois.
Uma estrutura mal definida não só dificulta manutenção, como impede crescimento saudável do sistema. Em projetos reais, estrutura não é detalhe — é fundação.
Uma organização bem pensada, com separação clara entre rotas, serviços, schemas, modelos e acesso a dados, faz o código respirar melhor. Facilita testes, onboarding de novos desenvolvedores e evolução contínua sem trauma.
Estrutura de Pastas que Uso e Recomendo
Depois de errar bastante, cheguei a uma estrutura que se mostrou estável e escalável:
app/
├── main.py
├── core/
│ ├── config.py
│ ├── security.py
│ └── settings.py
├── db/
│ ├── session.py
│ ├── base.py
│ └── migrations/
├── models/
│ ├── user.py
│ └── cliente.py
├── schemas/
│ ├── user_schema.py
│ └── cliente_schema.py
├── crud/
│ ├── user_crud.py
│ └── cliente_crud.py
├── services/
│ ├── user_service.py
│ └── cliente_service.py
├── api/
│ └── v1/
│ ├── router.py
│ └── endpoints/
│ ├── users.py
│ └── clientes.py
├── tests/
│ ├── unit/
│ └── integration/
└── utils/
Essa estrutura não é “a única correta”, mas resolve muito bem os problemas que iniciantes costumam enfrentar quando o projeto cresce.
FastAPI não falha com iniciantes — ele perdoa demais. E esse perdão cria projetos que funcionam, mas não se sustentam.
A maior lição que aprendi é simples: organização não é algo que você adiciona depois. Ela precisa existir desde o primeiro endpoint. Quem entende isso cedo constrói APIs mais seguras, mais fáceis de manter e muito mais profissionais.
FastAPI é rápido, mas arquitetura errada é lenta — e o tempo sempre cobra.