Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Temporal Bundle Laravel Package

vanta/temporal-bundle

Vanta Temporal Bundle integrates Temporal workflow orchestration into Laravel, with configurable workers, workflow and activity registration, and Artisan commands for running durable, fault-tolerant background processes and long-running tasks in a familiar package structure.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the SDK dependencies first. The bundle wraps temporal/sdk (and, for real concurrency, the RoadRunner worker). Require the bundle with Composer and let Flex register it, or add it manually to config/bundles.php.
  2. Confirm the config root key. Dump the reference before writing any YAML: php bin/console config:dump-reference <bundle_alias>. Read src/DependencyInjection/Configuration.php in the vendor tree — that file is the authoritative list of options (address, namespace, task queues, data converter, worker settings). Do not copy config from the README blindly; check it against the installed version.
  3. Stand up a local Temporal server. The fastest path is the Temporal CLI (temporal server start-dev) or the official docker-compose, which gives you localhost:7233 plus a UI on :8233. Point the bundle at it via env (TEMPORAL_ADDRESS / the bundle's address option) rather than hardcoding.
  4. Write one workflow and one activity, tag/register them the way the bundle expects (attributes, service tags, or an explicit workflows:/activities: config list), and start a worker with the bundle's console command.
  5. First end-to-end use case: an activity that does the risky I/O (HTTP call, Doctrine write, mail) and a workflow that orchestrates it with a retry policy and a timer. Trigger it from a controller or console command through the injected workflow client, return the workflow ID to the caller, then inspect it with temporal workflow show --id <id>. That loop — start, execute, inspect — is the whole day-to-day workflow.

Where to look first, in order: README → Configuration.php → the worker command class → the compiler pass that wires workflow/activity services. Those four files tell you 90% of how the bundle behaves.

Implementation Patterns

Separate orchestration from effects. Workflows are deterministic state machines; activities are ordinary Symfony services. Keep repositories, HTTP clients, mailers, and clocks out of workflow constructors and put them in activities. The bundle autowires both, so this is a discipline problem, not a technical one.

Register by tag, not by hand. Most bundles of this shape let you tag services (e.g. temporal.workflow / temporal.activity) or configure them in YAML. Tagging is preferable: it keeps registration next to the class and survives refactors. Group workflows and activities into task queues by domain (billing, notifications, ingestion) and run one worker process per queue, so a traffic spike in one domain doesn't starve another.

Trigger async, poll or signal for status. Controllers should call startWorkflow() with explicit WorkflowOptions — task queue, workflow execution timeout, retry policy, and a search attribute or memo carrying your entity ID — then return the workflow ID immediately. Use signals to push updates into a running workflow and queries to expose read-only state (progress, current step) to your UI. Never block a request on a long workflow result.

Activities are where Symfony integration happens. Inject the entity manager, the mailer, the HTTP client, and wrap each activity method around a single unit of work. Return primitives or DTOs — never Doctrine entities.

Use the Symfony serializer as a data converter if you have non-trivial DTOs. A custom DataConverterInterface bound to the bundle's converter service means payloads match what your HTTP layer already produces, and the Temporal UI becomes readable. If you don't need that, the default JSON converter with plain DTOs and public properties is less work.

Test in two layers. Activity services are plain PHP — test them like any other service. Workflows should be tested against WorkflowEnvironment::createTimeSkipping() (or a local dev server in CI), so timers and retries don't cost real wall-clock time. Run the worker in-process during tests with a test task queue to avoid collisions.

Version workflow code deliberately. Once a workflow type is running in production, use Workflow::getVersion() (patching) before changing the sequence of commands, or route new executions to a new task queue with the new code.

Gotchas and Tips

  • Determinism failures are the #1 source of pain. time(), rand(), sleep(), new \DateTime(), file_get_contents(), and static caches inside workflow methods all break replay. Use Workflow::now(), Workflow::timer(), and Workflow::sideEffect() for anything non-deterministic. If a worker logs "workflow task timeout" or nondeterminism errors, suspect this first, not the server.
  • PHP worker concurrency. The base SDK worker is effectively blocking; meaningful throughput needs the RoadRunner worker. Verify what the bundle actually ships — a plain bin/console worker command may be fine for a handful of workflows but will bottleneck under load. Run workers under supervisor/systemd with restart-on-failure, and restart them on deploy.
  • Deploys vs. running workflows. Long-running executions keep replaying old code. Rolling a new image while workflows are mid-flight is the classic way to get nondeterminism errors. Either drain task queues, or version aggressively.
  • Retries are on by default. An activity that throws gets retried until the retry policy gives up. For validation errors and permanent failures, throw a non-retryable ApplicationFailure; otherwise users see long stalls before an obvious error surfaces.
  • Set timeouts explicitly. Workflow execution timeout, run timeout, schedule-to-close, start-to-close, and heartbeat timeouts are all separate. The defaults will surprise you on long-running work — heartbeats in particular are what keep a stuck activity from hanging a workflow forever.
  • Serialization is stricter than you expect. Doctrine proxies, closures, resources, and large object graphs will fail or silently bloat history. Pass IDs and scalars between workflows and activities and re-fetch inside the activity.
  • TLS and Temporal Cloud. Connection options (API key / mTLS cert paths, namespace) usually differ from self-hosted; keep them in env vars and confirm the bundle's connection factory supports them before committing to Cloud.
  • Config quirks. The alias is often vendor-prefixed (vanta_temporal:), and some options only take effect through a compiler pass — clearing the cache is mandatory after changing them. If a workflow isn't registered, debug:container --tag=<tag> is faster than reading YAML.
  • Debugging toolkit. temporal workflow list/describe/show, temporal workflow stack for stuck executions, plus the Web UI's event history. Event history tells you exactly which activity or timer the workflow is parked on; worker logs tell you why it failed.
  • Extension points worth knowing: custom data converter, client and worker interceptors (good for tracing/log correlation and for injecting tenant context into headers), and a custom worker factory if you need to tune maxConcurrentActivityTaskPollers or similar.
  • Bus factor. With ~71 stars and zero dependents, this is a small, single-maintainer package. Pin an exact version in composer.json, read the source before leaning on undocumented behavior, and assume you may need to fork for a fix. The underlying temporal/sdk is the stable part; treat the bundle as thin glue you could replace with a few service definitions if it goes stale.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums