Skip to main content
Your compose tasks can be triggered by several different mechanisms. Triggers are configured in your manifest file for each task. Each task can have multiple triggers (one of each type), so triggers are configured as an array. Below is an overview of all the supported trigger types: cron, http, and onchain_event.

Local Task Execution

For locally testing tasks you can use the callTask CLI command. This works regardless of what trigger types a task has configured (and even for tasks with no triggers at all).

Trigger Task locally with CLI

Task Code

Task To Task Execution

Tasks can call other tasks directly — no trigger configuration required on the called task. This is done using the callTask context function.

Example

The process-data task will receive the payload and can return a response:

Chain Event Triggers

Tasks can be triggered by onchain events. The payload delivered to the task is the raw encoded log. Compose provides helpers for decoding the event in your task code — see Contracts for more details on decoding.
Onchain event triggers only fire when your app is deployed to the cloud. They do not fire during local development. To test a task with an onchain trigger locally, use callTask with a sample event payload:
You can copy a real event payload from a block explorer to use as test data.

Example event object sent as the payload to your task:

Example configuration for an onchain event trigger:

Task code

Here’s an example in which we decode the event with a contract class we’ve generated with goldsky compose codegen, see Contracts for more info.

Onchain Trigger Properties

Parallel processing

By default, onchain events are delivered one at a time: Goldsky sends an event, waits for your task to finish, then sends the next one. If a task takes 30 seconds and 2,000 events land in a burst, the last event runs hours late. Set parallel_processing: true to switch the trigger to queued, concurrent delivery. Events are written to an internal durable queue as they are indexed, and a worker in your app runs up to max_concurrency of them at the same time.
Your task code does not change. main(context, payload) still receives a single event, and each event still gets its own run ID, its own context function cache, and the same crash recovery as a serially delivered event. What to know before enabling it:
  • Ordering is not preserved. Events run concurrently, so a later event can finish before an earlier one. Only enable this if each event can be handled independently. Keep the default (serial) delivery if your task depends on events arriving in block order.
  • Concurrency is app-wide. One queue worker drains the queue for the whole app, so the first max_concurrency it finds on an onchain trigger sets the limit for every parallel trigger in that app. Set the same value on each trigger to avoid confusion.
  • Backpressure is handled for you. If the queue fills up, Compose rejects further deliveries with a 429 and Goldsky retries them with backoff, so events are not lost — they arrive later.
  • Reorgs cancel queued events. If an event is retracted (a reorg) while it is still sitting in the queue, the queued entry is removed and the task never runs for it. Events that have already started running are unaffected.
  • Operators can retune concurrency live. Goldsky can override max_concurrency on a running app via the COMPOSE_TRIGGER_CONCURRENCY environment variable, without a redeploy. Reach out in support if you need this while tuning.

Confirmations

Onchain triggers fire as soon as the event is indexed at the chain head, which means a reorg can retract an event your task already acted on. If the task moved real money — a settlement, a payout, a compliance gate — that is unrecoverable. Set confirmations: N to hold each event in the queue until its block is N blocks deep. Compose polls the chain head and releases the event once event block + N <= current block.
  • confirmations requires parallel_processing: true — the confirmation buffer is part of the queue. Setting it without parallel processing fails validation.
  • confirmations: 0 (the default) fires immediately, exactly as before.
  • While an event waits, it is held in the queue. If a reorg retracts it before it is released, the event is cancelled and your task never runs for it.
  • Choose the depth from your own risk tolerance: deeper is safer but adds latency roughly equal to N block times. Removing confirmations from your manifest releases anything still waiting on the next deploy.
This is the inbound counterpart to the outbound confirmation and reorg options on writeContract — see Reorg handling for transactions your task sends.

Failure Handling

Onchain-triggered tasks honor the task’s retry_config. When a task throws (or otherwise fails), Compose retries it up to max_attempts with the configured backoff. If every attempt fails, that event is dropped and the pipeline advances to the next one — it is not replayed. This means an unhandled exception in an onchain-triggered task only stalls delivery for the duration of your retry window, not indefinitely. If you want a failure to be visible without consuming retries, catch the error in your task and return normally — the run is recorded as successful and the pipeline moves on. With parallel_processing: true the same retry rules apply per event, but a failing event never stalls the others: each event is claimed from the queue independently, and one exhausting its retries doesn’t hold back the rest.

Cron Triggers

Tasks can be triggered on a schedule. Tasks triggered by cron are invoked with an empty payload ({}), since each invocation is generic.

Example

6-field (second-granularity) example

Pass a 6-field expression if you need second-level precision — the first field becomes seconds:

Cron Trigger Properties

HTTP Triggers

Tasks can be triggered by HTTP requests. This is often used to kick off compose tasks from your application logic. HTTP triggers accept any JSON payload you want for dynamic execution.

Example

Http Trigger Properties

Authenticated triggers require a Goldsky API token when the app is deployed, but can be called without auth when testing locally. Unauthenticated triggers can be called without auth both locally and when deployed.

Base URL

Locally, Compose runs on http://localhost:4000 by default. If port 4000 is taken, start picks the next free port up to 4009 and records it in .compose/.port. The base pattern for all task endpoints is:
When deployed to the cloud, tasks with an authenticated HTTP trigger (authentication: "auth_token") are reachable at:
When deployed to the cloud, tasks with an unauthenticated HTTP trigger (authentication: "none") are reachable at:

HTTP Request Format

When deployed to the cloud with authentication: "auth_token", you’ll need to pass a Goldsky API token:

Execute HTTP trigger without parameters

Execute an HTTP trigger with parameters

Response Format

Tasks return JSON responses with the data returned by the task’s main function. Calling this task:
via this request:
returns this JSON response:

Next Steps

Using Packages

You can use any sandbox compatible typescript packages with any package manager.

Debugging

Debug and monitor your apps