← Files TemporalARCHIVED FILE
skills/temporal-developer/references/typescript/advanced-features.md
5.6 KB · Oct 2, 2026 · 00:08 UTC
# TypeScript SDK Advanced Features
## Schedules
Create recurring workflow executions.
```typescript
import { Client, ScheduleOverlapPolicy } from '@temporalio/client';
const client = new Client();
// Create a schedule
const schedule = await client.schedule.create({
scheduleId: 'daily-report',
spec: {
intervals: [{ every: '1 day' }],
},
action: {
type: 'startWorkflow',
workflowType: 'dailyReportWorkflow',
taskQueue: 'reports',
args: [],
},
policies: {
overlap: ScheduleOverlapPolicy.SKIP,
},
});
// Manage schedules
const handle = client.schedule.getHandle('daily-report');
await handle.pause('Maintenance window');
await handle.unpause();
await handle.trigger(); // Run immediately
await handle.delete();
```
## Async Activity Completion
Complete an activity asynchronously from outside the activity function. Useful when the activity needs to wait for an external event.
**In the activity - return the task token:**
```typescript
import { CompleteAsyncError, activityInfo } from '@temporalio/activity';
export async function doSomethingAsync(): Promise<string> {
const taskToken: Uint8Array = activityInfo().taskToken;
setTimeout(() => doSomeWork(taskToken), 1000);
throw new CompleteAsyncError();
}
```
**External completion (from another process, machine, etc.):**
```typescript
import { Client } from '@temporalio/client';
async function doSomeWork(taskToken: Uint8Array): Promise<void> {
const client = new Client();
// does some work...
await client.activity.complete(taskToken, "Job's done!");
}
```
**When to use:**
- Waiting for human approval
- Waiting for external webhook callback
- Long-polling external systems
## Worker Tuning
Configure worker capacity for production workloads:
```typescript
import { Worker, NativeConnection } from '@temporalio/worker';
const worker = await Worker.create({
connection: await NativeConnection.connect({ address: 'temporal:7233' }),
taskQueue: 'my-queue',
workflowBundle: { codePath: require.resolve('./workflow-bundle.js') }, // Pre-bundled for production
activities,
// Workflow execution concurrency (default: 40)
maxConcurrentWorkflowTaskExecutions: 100,
// Activity execution concurrency (default: 100)
maxConcurrentActivityTaskExecutions: 200,
// Graceful shutdown timeout (default: 0)
shutdownGraceTime: '30 seconds',
// Max cached workflows (memory vs latency tradeoff)
maxCachedWorkflows: 1000,
});
```
**Key settings:**
- `maxConcurrentWorkflowTaskExecutions`: Max workflows running simultaneously (default: 40)
- `maxConcurrentActivityTaskExecutions`: Max activities running simultaneously (default: 100)
- `shutdownGraceTime`: Time to wait for in-progress work before forced shutdown
- `maxCachedWorkflows`: Number of workflows to keep in cache (reduces replay on cache hit)
## Preload Modules
`preloadModules` is a `string[]` bundler option that loads a list of modules once during reusable V8 context bootstrap; preloaded modules are then shared across workflows executing in the same V8 context. It is only beneficial when `reuseV8Context` is enabled, which is the default (`@default true`).
**Ahead-of-time bundling via `BundleOptions`:**
```typescript
import { bundleWorkflowCode } from '@temporalio/worker';
const { code } = await bundleWorkflowCode({
workflowsPath: require.resolve('./workflows'),
preloadModules: ['lodash', './workflow-helpers'],
});
```
**Startup bundling via `WorkerOptions.bundlerOptions`:**
```typescript
const worker = await Worker.create({
taskQueue: 'my-queue',
workflowsPath: require.resolve('./workflows'),
activities,
bundlerOptions: {
preloadModules: ['lodash', './workflow-helpers'],
},
});
```
**Constraints:**
- **`preloadModules` is only beneficial when `reuseV8Context` is enabled (default `true`). ** If `reuseV8Context` is disabled, leave the list empty.
- **Module top-level code runs once, before any workflow activator exists. ** Only preload modules whose initialization is safe to execute that early.
- **Preloading a module that internally stores per-workflow state will leak context across workflows and cause non-deterministic behavior. ** Remove such modules from `preloadModules`.
- **A module listed in both `preloadModules` and `ignoreModules` fails the bundle with `Cannot preload modules that are also ignored: '<module>'`. ** Remove the module from one of the two lists.
## Sinks
Sinks allow workflows to emit events for side effects (logging, metrics).
```typescript
import { proxySinks, Sinks } from '@temporalio/workflow';
// Define sink interface
export interface LoggerSinks extends Sinks {
logger: {
info(message: string, attrs: Record<string, unknown>): void;
error(message: string, attrs: Record<string, unknown>): void;
};
}
// Use in workflow
const { logger } = proxySinks<LoggerSinks>();
export async function myWorkflow(input: string): Promise<string> {
logger.info('Workflow started', { input });
const result = await someActivity(input);
logger.info('Workflow completed', { result });
return result;
}
// Implement sink in worker
const worker = await Worker.create({
workflowsPath: require.resolve('./workflows'), // Use workflowBundle for production
activities,
taskQueue: 'my-queue',
sinks: {
logger: {
info: {
fn(workflowInfo, message, attrs) {
console.log(`[${workflowInfo.workflowId}] ${message}`, attrs);
},
callDuringReplay: false, // Don't log during replay
},
error: {
fn(workflowInfo, message, attrs) {
console.error(`[${workflowInfo.workflowId}] ${message}`, attrs);
},
callDuringReplay: false,
},
},
},
});
```
SHA-256: a4433dfcd6df2cd26f877ebe3f3b9deba5fe7e6931b5e995d7045843ec06b760