Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

Context

Use oRPC context for type-safe dependency injection, providing initial context explicitly or injecting values 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 7, 2026

Was this page helpful?