On this page
Verified SDK sliceDeliberate protocol limitsDurability boundariesSource trailTiny worker and official TypeScript SDK
There are two runnable worker paths. Both use the same Frontend, History, Matching, and persistence services (memory or PostgreSQL).
| Path | Purpose | Command |
|---|---|---|
| Generator worker + running services | Observe timeout recovery with independently scoped workers | pnpm live |
| Stock TypeScript SDK over gRPC | Run ordinary async workflows in the SDK's real sandbox/Core runtime | pnpm start, then pnpm sdk:demo in another terminal |
Use Node 22 or 24 for the official SDK path (integration verified with Node 24). All @temporalio/* packages are pinned to 1.24.0. The server binds to loopback, port 7233 by default; PORT changes it. Set TEMPORAL_ADDRESS for the SDK consumer. Memory state survives worker loss while the server stays alive. PostgreSQL also survives complete server restarts.
Verified SDK slice
workflows.ts uses only @temporalio/workflow: proxyActivities, sleep, a signal handler, and condition. run.ts uses only the stock public client and worker APIs. Pointing its address at a real Temporal server also works; no toy imports or private SDK hooks are required.
pnpm test:sdk starts a server on an ephemeral port and checks:
- An activity fails once, retries, and returns a result.
- A workflow timer fires and a signal is handled.
WorkflowHandle.result()returns through the normal history RPC.- A separate worker process is killed with SIGKILL during an activity.
- A replacement worker completes attempt 2 and the original workflow finishes.
The gRPC adapter lives in service/frontend/grpc. Its listener registers every method of the generated public WorkflowService group. The published @temporalio/proto codec reads each binary request, json.ts converts it to proto3 JSON, and the generated schema validates it before Frontend sees it. Responses take the same path back. There is no per-method translation code: Frontend forwards public requests inside upstream's historyservice and matchingservice messages. See the gateway section for the code path.
History translates its compact internal events to public Temporal events at its RPC boundary, including scheduled/started/completed Workflow Tasks and linked activity/timer events. Matching builds each poll response from History's start response. Activity attempt failures stay out of the public history until the terminal attempt, so full replay sees a stable event prefix. Requests execute as fibers owned by the Frontend listener scope; shutdown interrupts and joins them. Cancellation removes waiting polls from Matching across each internal RPC hop; near the deadline, a poll returns an empty response, as upstream does. Execution lookups and signals validate the namespace/workflow ID/run ID together, and typed domain errors determine gRPC status codes. Task tokens carry opaque-to-the-SDK task identities; History validates whether they still name a live attempt.
Deliberate protocol limits
This is a tested subset, not general Temporal server compatibility. Use a registered namespace (default exists), a single normal task queue, JSON payloads, single-argument signals, and maxCachedWorkflows: 0. Sticky queues, eager dispatch, heartbeats, cancellation, queries, updates, child workflows, continue-as-new, local activities, codecs, search attributes, and worker versioning over gRPC are unsupported. Unsupported RPCs and command kinds return errors. History is returned without pagination; supplied continuation tokens are rejected. Workflow-ID reuse and start-request deduplication are not implemented. The Matching versioning labs still work through the in-process API.
Activity retries currently use immediate retry and maximum-attempt limits; the adapter does not reproduce production retry backoff, non-retryable failure classification, schedule-to-close timeouts, or detailed failure chains. Workflow Tasks use a one-second lab timeout and a 100ms failure retry delay. A large or slow workflow may repeatedly exceed that timeout. These limits keep the recovery path small enough to read.
The generator SDK emits sequential activity/timer commands. Signal waits are interpreted locally against received signal events. The official SDK owns its own replay, sandbox, and workflow concurrency; the server accepts command batches, but the verified slice is the sequential sample above. Arbitrary samples-typescript examples are not implied to work.
Durability boundaries
History commits execution state and generated work atomically in the configured store. Workflow and activity start-to-close timeouts reschedule lost work, and obsolete completions cannot change a newer attempt. Activity side effects can happen more than once. Stopping a toy worker interrupts reporting fibers; arbitrary user Promises may continue external side effects.
The PostgreSQL backend commits events, mutable state and generated tasks together. pnpm recovery demonstrates two independent process lifetimes connected only by that database. pnpm test:postgres also checks recovery after SIGKILL. See the persistence walkthrough for tables, inspection commands and remaining limits.
Source trail
- Temporal workflow lifecycle
- Workflow Task completion
- History timeout processing
- TypeScript SDK
- Effect ClusterWorkflowEngine: design inspiration for separating persistent work from activation lifetimes; tiny-temporal keeps its own Temporal protocol visible.