Bird
Raised Fist0
NestJSframework~10 mins

Pipe binding (parameter, method, controller, global) in NestJS - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Pipe binding (parameter, method, controller, global)
Request Received
↓
Global Pipes Run
↓
Controller Pipes Run
↓
Method Pipes Run
↓
Parameter Pipes Run
↓
Controller Method Executes
↓
Response Sent
The request passes through pipes in order: global, controller, method, then parameter before the controller method runs.
Execution Sample
NestJS
import { Controller, Get, Param, ParseIntPipe, UsePipes, ValidationPipe } from '@nestjs/common';

@UsePipes(new ValidationPipe())
@Controller('items')
export class ItemsController {
  @Get(':id')
  getItem(@Param('id', ParseIntPipe) id: number) {
    return { id };
  }
}
This code shows pipes bound at controller (UsePipes) and parameter (ParseIntPipe) levels.
Execution Table
StepPipe LevelPipe UsedInput ValueOutput ValueAction
1GlobalValidationPipe{ id: '42' }{ id: '42' }Validate input object structure
2ControllerValidationPipe{ id: '42' }{ id: '42' }Validate input again (same pipe instance)
3MethodNone{ id: '42' }{ id: '42' }No method-level pipe, pass through
4ParameterParseIntPipe'42'42Convert string '42' to number 42
5Controller MethodN/Aid=42{ id: 42 }Return object with numeric id
6ResponseN/A{ id: 42 }{ id: 42 }Send response to client
💡 All pipes processed; parameter pipe converted id to number; controller method executed with transformed value.
Variable Tracker
VariableStartAfter Global PipeAfter Controller PipeAfter Method PipeAfter Parameter PipeFinal
input{ id: '42' }{ id: '42' }{ id: '42' }{ id: '42' }4242
idundefinedundefinedundefinedundefined4242
Key Moments - 3 Insights
Why does the ParseIntPipe only run on the parameter and not on the whole request object?
Because parameter pipes apply only to the specific parameter they are bound to, as shown in step 4 of the execution_table where only the 'id' string is converted.
Why does the ValidationPipe run twice in this example?
It runs globally and again at the controller level because it is bound in both places, as seen in steps 1 and 2 of the execution_table.
What happens if a pipe transforms the input incorrectly?
The transformed value is passed to the next step; if invalid, it may cause errors or exceptions before the controller method runs.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the output value after the Parameter Pipe runs?
A'42'
B42
C{ id: '42' }
Dundefined
💡 Hint
Check step 4 in the execution_table where ParseIntPipe converts the string '42' to number 42.
At which step does the controller method execute?
AStep 3
BStep 4
CStep 5
DStep 6
💡 Hint
Step 5 shows the controller method receiving the transformed parameter and returning the response object.
If we remove the global ValidationPipe, which step would be skipped?
AStep 1
BStep 2
CStep 4
DStep 5
💡 Hint
Step 1 is the global pipe processing; removing global pipes skips this step.
Concept Snapshot
Pipe binding order in NestJS:
1. Global pipes run first on the whole request.
2. Controller-level pipes run next.
3. Method-level pipes run after.
4. Parameter-level pipes run last on specific parameters.
Each pipe can transform or validate data before the controller method executes.
Full Transcript
In NestJS, pipes can be bound at four levels: global, controller, method, and parameter. When a request arrives, it first passes through global pipes that apply to all routes. Then controller-level pipes run, affecting all methods in that controller. Next, method-level pipes run if defined, and finally, parameter-level pipes run on specific parameters. This layered approach allows precise control over data validation and transformation. For example, a global ValidationPipe can check the whole request structure, while a ParseIntPipe on a parameter converts a string to a number before the controller method uses it. This flow ensures data is clean and correctly typed before business logic runs.

Practice

(1/5)
1. What is the main purpose of binding a pipe to a parameter in NestJS?
easy
A. To define routing paths for the controller methods
B. To apply middleware logic before the controller handles the request
C. To globally change all incoming requests in the application
D. To transform or validate the specific parameter before the method uses it

Solution

  1. Step 1: Understand parameter-level pipe binding

    Binding a pipe to a parameter means the pipe runs only on that parameter to transform or validate it before the method uses it.
  2. Step 2: Differentiate from other bindings

    Middleware and global pipes affect broader scopes, not just a single parameter. Routing is unrelated to pipes.
  3. Final Answer:

    To transform or validate the specific parameter before the method uses it -> Option D
  4. Quick Check:

    Parameter pipe = transform/validate parameter [OK]
Hint: Parameter pipes affect only one input value [OK]
Common Mistakes:
  • Confusing parameter pipes with global pipes
  • Thinking pipes define routes
  • Mixing middleware with pipes
2. Which of the following is the correct syntax to bind a pipe globally in a NestJS application?
easy
A. @UsePipes(new ValidationPipe()) on a controller class
B. app.useGlobalPipes(new ValidationPipe());
C. @UsePipes(new ValidationPipe()) on a method
D. Bind pipe inside a method parameter decorator

Solution

  1. Step 1: Identify global pipe binding syntax

    Global pipes are bound using the app instance with app.useGlobalPipes(pipeInstance).
  2. Step 2: Differentiate from controller and method bindings

    @UsePipes decorator applies pipes at controller or method level, not globally.
  3. Final Answer:

    app.useGlobalPipes(new ValidationPipe()); -> Option B
  4. Quick Check:

    Global pipe = app.useGlobalPipes() [OK]
Hint: Global pipes use app.useGlobalPipes() method [OK]
Common Mistakes:
  • Using @UsePipes for global binding
  • Binding pipes inside method parameters for global effect
  • Confusing middleware with pipes
3. Given the following code, what will be the output if the incoming request has a query parameter age='25' (string)?
import { Controller, Get, Query, ParseIntPipe } from '@nestjs/common';

@Controller('users')
export class UserController {
  @Get()
  getUser(@Query('age', ParseIntPipe) age: number) {
    return { age, type: typeof age };
  }
}
medium
A. Runtime error due to type mismatch
B. {"age": "25", "type": "string"}
C. {"age": 25, "type": "number"}
D. {"age": null, "type": "object"}

Solution

  1. Step 1: Understand ParseIntPipe effect on query parameter

    ParseIntPipe converts the string '25' to the number 25 before passing it to the method.
  2. Step 2: Check returned object values

    The method returns an object with age as number 25 and type as 'number'.
  3. Final Answer:

    {"age": 25, "type": "number"} -> Option C
  4. Quick Check:

    ParseIntPipe converts string to number [OK]
Hint: ParseIntPipe converts string query to number [OK]
Common Mistakes:
  • Assuming age remains string
  • Expecting runtime error on conversion
  • Confusing type of returned value
4. Identify the error in this NestJS controller code snippet where a pipe is bound at the method level:
import { Controller, Get, UsePipes, ValidationPipe, Query } from '@nestjs/common';

@Controller('products')
export class ProductController {
  @Get()
  @UsePipes(ValidationPipe)
  findProduct(@Query('id') id: string) {
    return id;
  }
}
medium
A. ValidationPipe should be instantiated with 'new' keyword in @UsePipes
B. @UsePipes cannot be used on methods, only on controllers
C. Query decorator is missing a pipe binding
D. Controller decorator is missing parameters

Solution

  1. Step 1: Check @UsePipes decorator usage

    @UsePipes expects an instance of a pipe, so ValidationPipe must be called with 'new'.
  2. Step 2: Validate other parts

    @UsePipes can be used on methods, Query decorator is valid, Controller decorator is correct.
  3. Final Answer:

    ValidationPipe should be instantiated with 'new' keyword in @UsePipes -> Option A
  4. Quick Check:

    @UsePipes needs pipe instances [OK]
Hint: Always instantiate pipes with 'new' in decorators [OK]
Common Mistakes:
  • Passing pipe class instead of instance
  • Thinking @UsePipes only works on controllers
  • Missing pipe on parameter is not an error
5. You want to apply a custom pipe that trims whitespace from all string inputs in a controller and also validate numbers globally. Which binding strategy is best to achieve this cleanly?
hard
A. Bind the trim pipe at controller level and the number validation pipe globally
B. Bind both pipes globally to affect all controllers and methods
C. Bind both pipes only on method parameters where needed
D. Bind the trim pipe globally and the number validation pipe at method level

Solution

  1. Step 1: Understand scope of pipes for separation of concerns

    Trimming strings is specific to this controller's inputs, so controller-level binding keeps it scoped and clean.
  2. Step 2: Apply number validation globally

    Number validation is common across the app, so global binding ensures consistent validation everywhere.
  3. Final Answer:

    Bind the trim pipe at controller level and the number validation pipe globally -> Option A
  4. Quick Check:

    Controller pipe for specific, global pipe for common validation [OK]
Hint: Use controller pipes for specific, global pipes for common tasks [OK]
Common Mistakes:
  • Binding all pipes globally causing unnecessary processing
  • Binding all pipes only on parameters causing repetition
  • Mixing global and method-level without clear reason
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard