Use RPC
Expose typed procedures from a worker, the default calling path for your own frontends and workers.
RPC is the intended default for calling a Base worker: your frontend and your other workers invoke typed methods, TypeScript checks both ends, and there is no schema or codegen layer in between. Reach for REST when the caller is a third party; reach for GraphQL when clients need flexible queries over a graph. For your own calls, RPC.
Define an RPC service
@RpcService() marks the class; @Rpc() marks each procedure:
Everything you know from HTTP services carries over: @Injectable() constructor injection, @InjectRequestContext() parameters, @WithMiddleware at class or method scope, and thrown HttpErrors.
The implements NoteServiceInterface is the type-sharing contract your callers will consume — see Share Types.
Arguments: typed and validated
@RpcArgument(() => Type) deserializes the incoming JSON into a real class instance and runs validation — the same pipeline as @HttpBody and GraphQL inputs:
A failed validation never reaches your handler — the caller gets a structured validation error (see Call a Worker from the Web).
Notes on the decorator forms:
@RpcArgument(() => [Number])handles arrays; primitives (() => String,() => Number) coerce without a class.- A parameter without
@RpcArgumentreceives the raw JSON as-is: no class instance, no validation. Fine for pass-through payloads; prefer the decorated form at trust boundaries. @Rpc(() => ReturnType)additionally runs your return value through serialization — use it when returning@SerializableObjectclass instances; plain JSON return values need only bare@Rpc().
Register and expose
The service class goes in the same services list as everything else. Exposure is configured in the rpc settings slot:
- All procedures are served on a single
POST /__rpcroute (override withrpc.service.route). visibilitydefaults to'internal': only workers you allow can call in (see Worker-to-Worker Calls). Set'public'when browsers call the worker directly.- Visibility can be overridden per service (
@RpcService({ visibility: ... })) or per procedure (@Rpc({ visibility: ... })) — most specific wins. Handy for one public procedure on an otherwise internal service. - In local development, visibility is always effectively public so you can iterate freely.
- Like every service class, a decorated-but-unlisted service is not callable — registration is explicit.