Vapor Best Practices
- Concurrency
-
ALWAYS use Swift Concurrency (async /await ) over EventLoopFuture .
-
Use req.application.asyncController patterns if using custom executors, but standard async route handlers are preferred.
- Controllers & Routing
-
Organize routes into RouteCollection conformances.
-
Do not put logic in routes.swift ; delegate immediately to a Controller.
-
Group routes by feature (e.g., UsersController , AuthController ).
- Fluent (Database)
-
Use @Parent and @Children property wrappers correctly.
-
Always use DTOs (Data Transfer Objects) implementation Content for API requests/responses. NEVER return a Fluent Model directly to the client.
-
Run migrations via app.migrations.add(...) .
- Environment
-
Use Environment.get("KEY") for configuration.
-
Support Production vs Development modes explicitly in configure.swift .
Example Route
func boot(routes: RoutesBuilder) throws { let users = routes.grouped("users") users.get(use: index) }
@Sendable func index(req: Request) async throws -> [UserDTO] { let users = try await User.query(on: req.db).all() return users.map { $0.toDTO() } }