Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

Context

The context mechanism provides a type-safe dependency injection pattern. It lets you provide required dependencies explicitly or inject them dynamically through middleware.

Initial Context

Use initial context for values that come from the environment. Declare it with .$context, then provide it when executing the procedure:

const 
const base: Builder<{
    env: {
        DB_URL: string;
    };
} & object, Record<never, never>>
base
= const os: Builder<DefaultInitialContext & object, Record<never, never>>
The oRPC procedure builder. Chain methods like `.input`, `.use`, and `.handler` to define procedures, then compose them into routers.
@see{@link https://orpc.dev/docs/procedure Procedure}
os
.
Builder<DefaultInitialContext & object, Record<never, never>>.$context<{
    env: {
        DB_URL: string;
    };
}>(): Builder<{
    env: {
        DB_URL: string;
    };
} & object, Record<never, never>>
$context
<{
env: {
    DB_URL: string;
}
env
: { type DB_URL: stringDB_URL: string } }>()
export const
const getting: DecoratedProcedure<{
    env: {
        DB_URL: string;
    };
} & object, object, InitialInputSchema, Schema<void>, Record<never, never>, never>
getting
=
const base: Builder<{
    env: {
        DB_URL: string;
    };
} & object, Record<never, never>>
base
.
Builder<{ env: { DB_URL: string; }; } & object, Record<never, never>>.handler<void>(handler: ProcedureHandler<{
    env: {
        DB_URL: string;
    };
} & object, unknown, void, ORPCErrorConstructorMap<Record<never, never>>>): DecoratedProcedure<{
    env: {
        DB_URL: string;
    };
} & object, object, InitialInputSchema, Schema<void>, Record<never, never>, never>
handler
(async ({
context: {
    env: {
        DB_URL: string;
    };
} & object
context
}) => {
var console: Consoleconsole.Console.log(...data: any[]): void
The **`console.log()`** static method outputs a message to the console. [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)
log
(
context: {
    env: {
        DB_URL: string;
    };
} & object
context
.
env: {
    DB_URL: string;
}
env
)
})

Default Initial Context

To avoid repeating .$context declarations, you can define a default initial context type globally.

declare module '@orpc/server' {
  export interface DefaultInitialContext {
    env: { DB_URL: string }
  }
}

Injected Context

Injected context is injected at runtime through middleware:

const 
const base: BuilderWithMiddlewares<DefaultInitialContext & object, {
    env: {
        DB_URL: string;
    };
}, Record<never, never>>
base
= const os: Builder<DefaultInitialContext & object, Record<never, never>>
The oRPC procedure builder. Chain methods like `.input`, `.use`, and `.handler` to define procedures, then compose them into routers.
@see{@link https://orpc.dev/docs/procedure Procedure}
os
.
Builder<DefaultInitialContext & object, Record<never, never>>.use<{
    env: {
        DB_URL: string;
    };
}, DefaultInitialContext & object, Record<never, never>>(middleware: Middleware<DefaultInitialContext & object, {
    env: {
        DB_URL: string;
    };
}, unknown, unknown, Record<never, never>>): BuilderWithMiddlewares<DefaultInitialContext & object, {
    env: {
        DB_URL: string;
    };
}, Record<never, never>>
use
(async ({ next: MiddlewareNext<unknown>
Invoke to continue the middleware chain.
next
}) =>
next: MiddlewareNext
<{
    env: {
        DB_URL: string;
    };
}>(options: {
    context: {
        env: {
            DB_URL: string;
        };
    };
}) => MiddlewareResult<{
    env: {
        DB_URL: string;
    };
}, unknown>
Invoke to continue the middleware chain.
next
({
context: {
    env: {
        DB_URL: string;
    };
}
context
: {
env: {
    DB_URL: string;
}
env
: { type DB_URL: stringDB_URL:
const env: {
    DB_URL: string;
}
env
.type DB_URL: stringDB_URL },
}, })) export const
const getting: DecoratedProcedure<DefaultInitialContext & object, {
    env: {
        DB_URL: string;
    };
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
getting
=
const base: BuilderWithMiddlewares<DefaultInitialContext & object, {
    env: {
        DB_URL: string;
    };
}, Record<never, never>>
base
.
BuilderWithMiddlewares<DefaultInitialContext & object, { env: { DB_URL: string; }; }, Record<never, never>>['handler']<void>(handler: ProcedureHandler<Omit<DefaultInitialContext & object, "env"> & {
    env: {
        DB_URL: string;
    };
}, unknown, void, ORPCErrorConstructorMap<Record<never, never>>>): DecoratedProcedure<DefaultInitialContext & object, {
    env: {
        DB_URL: string;
    };
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
handler
(async ({
context: Omit<DefaultInitialContext & object, "env"> & {
    env: {
        DB_URL: string;
    };
}
context
}) => {
var console: Consoleconsole.Console.log(...data: any[]): void
The **`console.log()`** static method outputs a message to the console. [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)
log
(
context: Omit<DefaultInitialContext & object, "env"> & {
    env: {
        DB_URL: string;
    };
}
context
.
env: {
    DB_URL: string;
}
env
)
})

Combining Initial and Injected Context

In many cases, you will use both. Use initial context for environment-specific values, such as database URLs, and injected context for runtime data, such as authenticated users.

const 
const base: Builder<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, Record<never, never>>
base
= const os: Builder<DefaultInitialContext & object, Record<never, never>>
The oRPC procedure builder. Chain methods like `.input`, `.use`, and `.handler` to define procedures, then compose them into routers.
@see{@link https://orpc.dev/docs/procedure Procedure}
os
.
Builder<DefaultInitialContext & object, Record<never, never>>.$context<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
}>(): Builder<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, Record<never, never>>
$context
<{ headers: Headersheaders: Headers,
env: {
    JWT_SECRET: string;
}
env
: { type JWT_SECRET: stringJWT_SECRET: string } }>()
const
const requireAuth: DecoratedMiddleware<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, unknown, any, Record<never, never>>
requireAuth
=
const base: Builder<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, Record<never, never>>
base
.
Builder<{ headers: Headers; env: { JWT_SECRET: string; }; } & object, Record<never, never>>.middleware<{
    user: {
        userId: number;
    };
}, unknown, any>(middleware: Middleware<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, unknown, any, Record<never, never>>): DecoratedMiddleware<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, unknown, any, Record<never, never>>
middleware
(async ({
context: {
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object
context
, next: MiddlewareNext<any>
Invoke to continue the middleware chain.
next
}) => {
const
const user: {
    userId: number;
} | null
user
=
function parseJWT(token: string | undefined, secret: string): {
    userId: number;
} | null
parseJWT
(
context: {
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object
context
.headers: Headersheaders.Headers.get(name: string): string | null
The **`get()`** method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get)
get
('authorization')?.String.split(separator: string | RegExp, limit?: number): string[] (+1 overload)
Split a string into substrings using the specified separator and return them as an array.
@paramseparator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.@paramlimit A value used to limit the number of elements returned in the array.
split
(' ')[1],
context: {
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object
context
.
env: {
    JWT_SECRET: string;
}
env
.type JWT_SECRET: stringJWT_SECRET
) if (!
const user: {
    userId: number;
} | null
user
) {
throw new new ORPCError<"UNAUTHORIZED", unknown>(code: "UNAUTHORIZED", options?: ORPCErrorOptions<unknown> | undefined): ORPCError<"UNAUTHORIZED", unknown>
Typed error carrying a `code`, a `message`, and optional `data`. Throw it from handlers or middleware to produce typed error responses on the client.
@see{@link https://orpc.dev/docs/error-handling#orpcerror-class Error Handling - ORPCError Class}
ORPCError
('UNAUTHORIZED')
} return
next: MiddlewareNext
<{
    user: {
        userId: number;
    };
}>(options: {
    context: {
        user: {
            userId: number;
        };
    };
}) => MiddlewareResult<{
    user: {
        userId: number;
    };
}, any>
Invoke to continue the middleware chain.
next
({
context: {
    user: {
        userId: number;
    };
}
context
: {
user: {
    userId: number;
}
user
} })
}) const
const getting: DecoratedProcedure<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
getting
=
const base: Builder<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, Record<never, never>>
base
.
Builder<{ headers: Headers; env: { JWT_SECRET: string; }; } & object, Record<never, never>>.use<{
    user: {
        userId: number;
    };
}, {
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, Record<never, never>>(middleware: Middleware<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, unknown, unknown, Record<never, never>>): BuilderWithMiddlewares<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, Record<never, never>>
use
(
const requireAuth: DecoratedMiddleware<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, unknown, any, Record<never, never>>
requireAuth
)
.
BuilderWithMiddlewares<{ headers: Headers; env: { JWT_SECRET: string; }; } & object, { user: { userId: number; }; }, Record<never, never>>['handler']<void>(handler: ProcedureHandler<Omit<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, "user"> & {
    user: {
        userId: number;
    };
}, unknown, void, ORPCErrorConstructorMap<Record<never, never>>>): DecoratedProcedure<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, {
    user: {
        userId: number;
    };
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
handler
(async ({
context: Omit<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, "user"> & {
    user: {
        userId: number;
    };
}
context
}) => {
var console: Consoleconsole.Console.log(...data: any[]): void
The **`console.log()`** static method outputs a message to the console. [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)
log
(
context: Omit<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, "user"> & {
    user: {
        userId: number;
    };
}
context
.
env: {
    JWT_SECRET: string;
}
env
)
var console: Consoleconsole.Console.log(...data: any[]): void
The **`console.log()`** static method outputs a message to the console. [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)
log
(
context: Omit<{
    headers: Headers;
    env: {
        JWT_SECRET: string;
    };
} & object, "user"> & {
    user: {
        userId: number;
    };
}
context
.
user: {
    userId: number;
}
user
)
})

Last updated on August 6, 2026

Was this page helpful?