Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

Contract Implementation

Implementing a contract means adding business logic to each procedure defined in that contract. It ensures every implementation stays consistent by verifying that each handler matches the procedure’s expected shape.

Implementer

The implement function turns a contract into an implementer. Use it to build procedures, routers, and create middleware with full type safety.

import { function implement<TContract extends RouterContract, TInitialContext extends Context = DefaultInitialContext>(contract: TContract, config?: ProcedureConfig): Implementer<TContract, TInitialContext & object>
Turns a contract into an implementer, used to implement the contract's procedures, routers, and middleware with full type safety.
@see{@link https://orpc.dev/docs/contract/implementation#implementer Contract Implementation - Implementer}
implement
} from '@orpc/server'
const
const implementer: Implementer<{
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}, {
    ...;
} & object>
implementer
=
implement<{
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}, DefaultInitialContext>(contract: {
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}, config?: ProcedureConfig): Implementer<...>
Turns a contract into an implementer, used to implement the contract's procedures, routers, and middleware with full type safety.
@see{@link https://orpc.dev/docs/contract/implementation#implementer Contract Implementation - Implementer}
implement
(
const contract: {
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}
contract
)
.
$context<{
    something?: string;
}>(): Implementer<{
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<...>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}, {
    something?: string;
} & object>
$context
<{ something?: string | undefinedsomething?: string }>() // <- define initial context
const implementer: Implementer<{
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}, {
    ...;
} & object>
implementer
.
planet: Public<SharedRouterImplementer<{
    list: ProcedureContractBuilderWithInputOutput<ZodObject<{
        limit: ZodOptional<ZodNumber>;
        cursor: ZodDefault<ZodNumber>;
    }, $strip>, ZodArray<ZodObject<{
        id: ZodNumber;
        name: ZodString;
        description: ZodOptional<ZodString>;
    }, $strip>>, object>;
    find: ProcedureContractBuilderWithInputOutput<ZodObject<{
        id: ZodNumber;
    }, $strip>, ZodObject<{
        id: ZodNumber;
        name: ZodString;
        description: ZodOptional<ZodString>;
    }, $strip>, object>;
    create: ProcedureContractBuilderWithInputOutput<...>;
}, {
    ...;
} & object>> & {
    ...;
}
planet
.
  • create
  • find
  • lazy
  • list
  • middleware
  • router
  • use
list: ProcedureImplementer<{
    ...;
} & object, object, ZodObject<...>, ZodArray<...>, object>
list
// // // //

Initial Context

Use .$context to declare the initial context required for a procedure to execute. Learn more in the Context Documentation.

Implementing Procedures

Define a .handler for a procedure contract to provide its business logic.

const 
const listPlanet: ImplementedProcedure<DefaultInitialContext & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<ZodString>;
}, $strip>>, object>
listPlanet
=
const implementer: Implementer<{
    planet: {
        list: ProcedureContractBuilderWithInputOutput<ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ProcedureContractBuilderWithInputOutput<ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>, object>;
        create: ProcedureContractBuilderWithInputOutput<...>;
    };
}, DefaultInitialContext & object>
implementer
.
planet: Public<SharedRouterImplementer<{
    list: ProcedureContractBuilderWithInputOutput<ZodObject<{
        limit: ZodOptional<ZodNumber>;
        cursor: ZodDefault<ZodNumber>;
    }, $strip>, ZodArray<ZodObject<{
        id: ZodNumber;
        name: ZodString;
        description: ZodOptional<ZodString>;
    }, $strip>>, object>;
    find: ProcedureContractBuilderWithInputOutput<ZodObject<{
        id: ZodNumber;
    }, $strip>, ZodObject<{
        id: ZodNumber;
        name: ZodString;
        description: ZodOptional<ZodString>;
    }, $strip>, object>;
    create: ProcedureContractBuilderWithInputOutput<...>;
}, DefaultInitialContext & object>> & {
    ...;
}
planet
.
list: ProcedureImplementer<DefaultInitialContext & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<ZodString>;
}, $strip>>, object>
list
.
ProcedureImplementer<DefaultInitialContext & object, object, ZodObject<{ limit: ZodOptional<ZodNumber>; cursor: ZodDefault<ZodNumber>; }, $strip>, ZodArray<...>, object>['use']<object, DefaultInitialContext & object, object>(middleware: Middleware<DefaultInitialContext & object, object, {
    cursor: number;
    limit?: number | undefined;
}, {
    id: number;
    name: string;
    description?: string | undefined;
}[], object>): ProcedureImplementer<DefaultInitialContext & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<...>;
}, $strip>>, object>
use
(const requireAuth: DecoratedMiddleware<DefaultInitialContext & object, object, unknown, any, object>requireAuth) // <- Apply authentication middleware
.
ProcedureImplementer<DefaultInitialContext & object, object, ZodObject<{ limit: ZodOptional<ZodNumber>; cursor: ZodDefault<ZodNumber>; }, $strip>, ZodArray<...>, object>['handler'](handler: ProcedureHandler<DefaultInitialContext & object, {
    cursor: number;
    limit?: number | undefined;
}, {
    id: number;
    name: string;
    description?: string | undefined;
}[] | AnyORPCError, object>): ImplementedProcedure<DefaultInitialContext & object, object, ZodObject<{
    limit: ZodOptional<ZodNumber>;
    cursor: ZodDefault<ZodNumber>;
}, $strip>, ZodArray<ZodObject<{
    id: ZodNumber;
    name: ZodString;
    description: ZodOptional<...>;
}, $strip>>, object>
handler
(({
input: {
    cursor: number;
    limit?: number | undefined;
}
input
}) => {
// Your logic for listing planets return [] })

Implementing Routers

Create the root router with .router to assemble your API. This enables full type-checking and runtime contract enforcement.

const router = implementer.router({
  planet: {
    list: listPlanet,
    find: findPlanet,
    create: createPlanet,
  },
})

Extending Router

Like a normal router, an implementer router can also be extended with shared behavior. For example, you can apply authentication middleware to every procedure:

const router = implementer.use(requireAuth).router({
  planet: {
    list: listPlanet,
    find: findPlanet,
    create: createPlanet,
  },
})

Creating Middleware

The implementer can also create middleware. Middleware created this way can infer the contract’s typesafe errors. If not all contracts define the same errors, use the in operator to check that an error exists before using it.

const ratelimit = implementer.middleware(async ({ next, errors }) => {
  if ('TOO_MANY_REQUESTS' in errors) {
    // Apply rate limiting only when TOO_MANY_REQUESTS is defined by the contract.
    if (isRatelimitReached) {
      throw errors.TOO_MANY_REQUESTS()
    }
  }

  return next()
})

Reusability

Each implementer call creates a new instance, which avoids reference issues and makes contracts easy to reuse and extend.

const pub = implementer // Base setup for procedures that publish
const authed = implementer.use(requireAuth) // Extends 'pub' with authentication

const listPlanets = pub.planet.list.handler(({ input }) => {
  // Your logic for listing planets without authentication
  return []
})

const createPlanet = authed.planet.create.handler(({ input }) => {
  // Your logic for creating planets with authentication
  return { }
})

This pattern helps prevent duplication while maintaining flexibility.

Last updated on August 6, 2026

Was this page helpful?