A guard implements CanActivate and returns a boolean to allow or block a request. Unlike middleware, guards run after routing — they know which controller and handler will process the request, enabling metadata-driven authorization decisions. Use guards for auth; use middleware for transport-level concerns that don't depend on the route.
Guards — run after routing; know the target handler; can read @SetMetadata() via Reflector.
Middleware — run before routing; cannot read route metadata; suited for request preprocessing.
Use guards for: JWT verification, RBAC, API key validation, subscription checks.
Use middleware for: logging, CORS, body parsing, session hydration, rate limiting.
Guards can return boolean, Promise<boolean>, or Observable<boolean>.