Skip to content

Add eager start support for standalone activities - #12349

Open
wenlong-gu wants to merge 22 commits into
temporalio:mainfrom
wenlong-gu:codex/saa-eager-start-saa
Open

wenlong-gu wants to merge 22 commits into
temporalio:mainfrom
wenlong-gu:codex/saa-eager-start-saa

Conversation

@wenlong-gu

@wenlong-gu wenlong-gu commented Oct 2, 2026 •

Copy link
Copy Markdown

What changed?

This PR adds eager start support for Standalone Activities (SAA). When an eligible client requests eager start, the server can return the first Activity task directly in the StartActivityExecution response, avoiding the initial task-queue dispatch round trip.

The PR falls back to normal Matching dispatch when eager delivery is not admitted.

Why?

The eager start feature has been implemented for WFA, so this change is to mirror that flow to save latency.

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

Local benchmark

Measured 200 paired runs using an in-process Temporal server test cluster:

Path p50 p95 p99
Normal SAA 2.372 ms 58.654 ms 88.855 ms
Eager SAA 1.588 ms 5.028 ms 7.362 ms

This is approximately 33% lower p50 and 91–92% lower p95/p99 latency in the
local environment. It measures server-side task delivery only; it excludes SDK
worker scheduling, Activity business-code execution, network latency, and
production load.

@CLAassistant

CLAassistant commented Oct 2, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@wenlong-gu
wenlong-gu marked this pull request as ready for review October 2, 2026 15:25
@wenlong-gu
wenlong-gu requested review from a team as code owners October 2, 2026 15:25
@wenlong-gu
wenlong-gu requested review from fretz12 and a balanced review from Copilot October 2, 2026 19:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The eager response omits standard execution metadata, loses SDK metadata, and lacks the documented rollout metrics.

Review effort: Balanced
Findings: 4 Medium severity

Open (4)
What changed in this PR

Adds eager delivery of the first standalone Activity task, bypassing initial Matching dispatch while preserving persisted state and timeout protection.

Changes:

  • Adds namespace-gated eager-start handling and task construction.
  • Extends state-machine, parity, and functional coverage.
  • Documents lifecycle, safety, and performance behavior.
File Description
tests/​activity_workflow_driver.go Adds eager workflow Activity driver.
tests/​activity_standalone_test.go Tests eager response deduplication.
tests/​activity_standalone_driver.go Supports eager standalone tasks.
tests/​activity_parity_test.go Adds eager retry parity coverage.
tests/​activity_driver.go Models eagerly started attempts.
docs/​architecture/​saa-eager-start-plan.md Documents design and validation.
chasm/​lib/​activity/​statemachine.go Adds atomic eager-start transition.
chasm/​lib/​activity/​statemachine_test.go Tests eager transition tasks.
chasm/​lib/​activity/​responses.go Builds eager worker responses and tokens.
chasm/​lib/​activity/​model/​vocabulary.go Adds eager model configuration.
chasm/​lib/​activity/​model/​model.go Models initially started state.
chasm/​lib/​activity/​model/​model_test.go Tests eager model behavior.
chasm/​lib/​activity/​handler.go Creates and returns eager tasks.
chasm/​lib/​activity/​frontend.go Applies eligibility fallback.
chasm/​lib/​activity/​frontend_test.go Tests fallback conditions.
chasm/​lib/​activity/​config.go Adds namespace eager-start configuration.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread chasm/lib/activity/responses.go Outdated
Comment thread chasm/lib/activity/statemachine.go
Comment thread docs/architecture/saa-eager-start-plan.md Outdated
Comment thread tests/activity_parity_test.go
Comment thread docs/architecture/saa-eager-start-plan.md Outdated
Comment thread chasm/lib/activity/responses.go Outdated
Comment thread common/metrics/metric_defs.go Outdated
Comment thread common/metrics/metric_defs.go Outdated
Comment thread common/metrics/metric_defs.go Outdated
Comment thread chasm/lib/activity/frontend.go Outdated
Comment thread chasm/lib/activity/statemachine.go
Comment thread chasm/lib/activity/statemachine.go Outdated
Comment thread cmd/tools/check-dependencies/main.go
Comment thread Makefile
Comment thread tests/activity_standalone_test.go
@fretz12

fretz12 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

can you make the PR desc follow the standard template? And personally I'd prefer to just keep it concise and to the point rather than too much AI noise

wenlong-gu added a commit to temporalio/api that referenced this pull request Oct 8, 2026
## Task overview

Part 1 of 3 for ACT-1118, adding eager start for Standalone Activities
(SAA).

Today, an SAA start must create the activity, enqueue a dispatch task,
send it
through Matching, and wait for a worker poll. This adds queue latency
even when
the caller has a ready local worker.

The complete solution lets an eligible `StartActivityExecution` request
return
the first Activity task directly in its response. The server persists
the
activity before returning that task and skips only the initial Matching
dispatch.

For safety, an eager task is returned only for a newly created
execution.
Same-request-ID retries and conflicts such as `USE_EXISTING` return the
existing execution without re-delivering the task, because Activity code
may
have external side effects.

## Scope of this PR

Adds the additive public API contract:

- `StartActivityExecutionRequest.request_eager_execution`
- `StartActivityExecutionResponse.eager_activity_task`

There is no runtime server behavior in this PR.

## Related PRs

- API-Go: temporalio/api-go#319 updates this
proto
  submodule and regenerates the Go API types.
- Temporal: temporalio/temporal#12349 implements
  request eligibility, the eager state transition, task construction,
  retry/conflict safety, and tests.

## Validation

- API linter passes.

## Benchmark context

This contract-only PR has no runtime behavior. The Temporal
implementation was
measured locally in an in-process server test cluster over 200 paired
runs:

| Path | p50 | p95 | p99 |
|---|---:|---:|---:|
| Normal SAA | 2.372 ms | 58.654 ms | 88.855 ms |
| Eager SAA | 1.588 ms | 5.028 ms | 7.362 ms |

The measurement covers server-side task delivery only; it excludes SDK
worker
scheduling, user Activity execution, network latency, and production
load.
temporal-cicd Bot pushed a commit to temporalio/api-go that referenced this pull request Oct 8, 2026
## Task overview

Part 1 of 3 for ACT-1118, adding eager start for Standalone Activities
(SAA).

Today, an SAA start must create the activity, enqueue a dispatch task,
send it
through Matching, and wait for a worker poll. This adds queue latency
even when
the caller has a ready local worker.

The complete solution lets an eligible `StartActivityExecution` request
return
the first Activity task directly in its response. The server persists
the
activity before returning that task and skips only the initial Matching
dispatch.

For safety, an eager task is returned only for a newly created
execution.
Same-request-ID retries and conflicts such as `USE_EXISTING` return the
existing execution without re-delivering the task, because Activity code
may
have external side effects.

## Scope of this PR

Adds the additive public API contract:

- `StartActivityExecutionRequest.request_eager_execution`
- `StartActivityExecutionResponse.eager_activity_task`

There is no runtime server behavior in this PR.

## Related PRs

- API-Go: #319 updates this
proto
  submodule and regenerates the Go API types.
- Temporal: temporalio/temporal#12349 implements
  request eligibility, the eager state transition, task construction,
  retry/conflict safety, and tests.

## Validation

- API linter passes.

## Benchmark context

This contract-only PR has no runtime behavior. The Temporal
implementation was
measured locally in an in-process server test cluster over 200 paired
runs:

| Path | p50 | p95 | p99 |
|---|---:|---:|---:|
| Normal SAA | 2.372 ms | 58.654 ms | 88.855 ms |
| Eager SAA | 1.588 ms | 5.028 ms | 7.362 ms |

The measurement covers server-side task delivery only; it excludes SDK
worker
scheduling, user Activity execution, network latency, and production
load.
# Conflicts:
#	go.mod
#	go.sum
#	tests/mixedbrain/go.mod
#	tests/mixedbrain/go.sum
@wenlong-gu
wenlong-gu force-pushed the codex/saa-eager-start-saa branch from 63cae51 to e75545e Compare October 9, 2026 00:43
Comment thread chasm/lib/activity/responses.go
Comment thread chasm/lib/activity/handler.go
Comment thread chasm/lib/activity/handler.go Outdated
VegetarianOrc pushed a commit to temporalio/api that referenced this pull request Oct 12, 2026
## Task overview

Part 1 of 3 for ACT-1118, adding eager start for Standalone Activities
(SAA).

Today, an SAA start must create the activity, enqueue a dispatch task,
send it
through Matching, and wait for a worker poll. This adds queue latency
even when
the caller has a ready local worker.

The complete solution lets an eligible `StartActivityExecution` request
return
the first Activity task directly in its response. The server persists
the
activity before returning that task and skips only the initial Matching
dispatch.

For safety, an eager task is returned only for a newly created
execution.
Same-request-ID retries and conflicts such as `USE_EXISTING` return the
existing execution without re-delivering the task, because Activity code
may
have external side effects.

## Scope of this PR

Adds the additive public API contract:

- `StartActivityExecutionRequest.request_eager_execution`
- `StartActivityExecutionResponse.eager_activity_task`

There is no runtime server behavior in this PR.

## Related PRs

- API-Go: temporalio/api-go#319 updates this
proto
  submodule and regenerates the Go API types.
- Temporal: temporalio/temporal#12349 implements
  request eligibility, the eager state transition, task construction,
  retry/conflict safety, and tests.

## Validation

- API linter passes.

## Benchmark context

This contract-only PR has no runtime behavior. The Temporal
implementation was
measured locally in an in-process server test cluster over 200 paired
runs:

| Path | p50 | p95 | p99 |
|---|---:|---:|---:|
| Normal SAA | 2.372 ms | 58.654 ms | 88.855 ms |
| Eager SAA | 1.588 ms | 5.028 ms | 7.362 ms |

The measurement covers server-side task delivery only; it excludes SDK
worker
scheduling, user Activity execution, network latency, and production
load.
@wenlong-gu
wenlong-gu requested a review from a team as a code owner October 12, 2026 20:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants