Skip to main content
Services hold the business logic. Routes should stay thin enough to read at a glance, and anything more than parsing a request and returning a response belongs here.
services/user_service.py

Transactions

@transactional commits when the method returns and rolls back when it raises. Since exceptions already map to HTTP responses, a validation failure rolls back the transaction and returns a 400 with no explicit handling.

Injecting a service into a route

Singleton services

For initialization that should happen once rather than per request:

Generating a service