Scheduled Jobs API
This page is the reference for public signatures, validation and errors. The Jobs guide covers configuration, development, deployment and troubleshooting; the contract defines execution guarantees.
defineJob
Import the functions and types you need from the public package entry:
These are signature references, not declarations to copy into a task file:
defineJob() synchronously validates and returns a framework-marked definition, freezing its top-level object; nested docs/tags are not deeply frozen. Unknown top-level fields and invalid explicit values do not use defaults. isVextJobDefinition() recognizes a definition's type; it does not prove valid module declarations, successful loading, readiness or execution.
Handler context
Definition rules
Default discovery recursively selects .ts/.js/.mjs/.cjs/.mts/.cts in src/jobs. Each selected file contains one finite default SDK Job; CommonJS uses equivalent module.exports. Ordinary helpers, types and constants are allowed. Named Jobs are not an additional registration entry.
Recognizable default aliases, dynamic fields and finite relative default re-exports within project source boundaries are supported; both entry and definition must satisfy the rules. Factories/conditional defaults, arrays, named-only Jobs, additional SDK declarations (including unused positions), Job-valued named aliases, user getters/Proxies and later export mutation are unsupported. This finite authoring grammar is not a whole-program side-effect sandbox. Do not run business work or create independent timers at module top level.
Explicit name wins; otherwise remove the relative path extension and trailing /index, then join with dots without changing camelCase. Disabled definitions participate in duplicate checks. Global disable skips discovery; per-task disable still validates fields, declaration count, TTL and names, only exempting scheduling and future-point requirements.
Build validation precedes optimization; production may contain only valid build output and need not deploy src for Jobs. See discovery examples.
VextJobsConfig
Configure jobs in existing src/config/default.ts or the selected profile, using normal configuration merge order. All fields are optional:
Unknown fields are rejected. Directory/array structure remains valid even with global disable; import differences between global and per-task switches are described above.
Redis configuration
One process or one built-in Cluster needs no Redis. Configure jobs.redis when independent applications need shared coordination; an environment URL without this object does not enable it.
Connection precedence is client > url > uri > VEXT_REDIS_URL > REDIS_URL. Invalid clients, including null, never fall back to a URL. Undefined addresses allow fallback; explicit empty url does not. Active tasks require usable connectivity and initialization script capabilities; failure rejects startup. No enabled tasks means no unnecessary connection/probe, while configuration structure and TTL still validate.
The default namespace uses package name, VEXT_CONFIG (default default) and NODE_ENV (default production); an unreadable package name falls back to vextjs-app. The logical prefix is vext:<namespace>:job:. Namespace normalization removes leading @, converts path separators to dots, replaces unsupported characters with hyphens, collapses repeated separators and trims edge separators. For example, @team/my-app:production:production becomes team.my-app:production:production. An empty normalized namespace uses vextjs-app. Whitespace-only keyPrefix leaves an explicit or automatic namespace in effect.
A shared domain requires matching Redis target, effective prefix, task name and definition. Name/prefix changes create a different identity; TTL does not form identity. Jobs does not borrow cache, Session or rate-limit Redis configuration. Each task renews with its effective TTL, which must match across replicas. shutdown.timeout is in seconds and shares one application-wide shutdown budget.
Documentation source
Project documentation selection
These settings affect static documentation only, not runtime discovery, eligibility or scheduling:
Fields inherit/override individually. openapi.docs.code.enabled:false disables overall code documentation without stopping tasks. Disabled definitions may appear. Unknown/partial evidence stays unresolved; runtimeVerified:false proves neither startup nor execution. See default viewing and optional overrides.
Errors and execution boundaries
Scheduling deduplication does not guarantee exactly-once business side effects. Partitions, state loss and ignored cancellation still require business idempotency; see the contract.
Testing entry point
Import createTestJobScheduler, CreateTestJobSchedulerOptions and TestJobScheduler from vextjs/testing. It takes explicit definitions and a controlled clock without discovery or real timers. Ordinary createTestApp does not load Jobs. See the testing API and guide.