You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Native: enforce the structural limits published PHP Server enforces #612
For deployments whose workflows run on external workers, published PHP Server enforces these Workflow package structural limits, configured by DW_V2_LIMIT_* (legacy WORKFLOW_V2_LIMIT_*):
Limit
Default
Where PHP applies it
memo_size_bytes
262144
memo upserts
command_batch_size
1000
upper bound on a command's parallel_group_size metadata
pending_signal_count
5000
signal intake
pending_update_count
500
update intake
payload_size_bytes
2097152
signal and update arguments, and an activity's successful result
The native server enforces only memo_size_bytes. A deployment that relies on one of the others, at its default or a configured value, gets no refusal from native where PHP refuses.
The other package limits (pending activities, children and timers, history transaction size, search attribute size) are checked only on PHP's in-process execution path, which external workers do not reach. See the evidence in the first comment.
Goal
For the same request and configuration, native refuses exactly where published PHP Server refuses, with PHP's status, reason and limit metadata. The run's state after a refusal matches PHP's.
Acceptance
Native reads each applicable DW_V2_LIMIT_* setting with PHP's precedence and casts, and a zero or negative value behaves as in PHP.
Differential tests against published PHP cover each enforced limit at, below and above its boundary on SQLite, MySQL/MariaDB and PostgreSQL.
Scope from reading the published 2.5.14 image (ghcr.io/durable-workflow/server@sha256:28fa0f39…), Workflow package vendor/durable-workflow/workflow/src/V2:
Enforced for external-worker deployments
memo_size_bytes: DefaultWorkflowTaskBridge (memo upserts). Native already enforces it.
command_batch_size: only as the upper bound on a command's parallel_group_size metadata (DefaultWorkflowTaskBridge::parallelMetadataEntry, WorkflowCommandNormalizer::parallelMetadataEntry). Larger metadata is treated as invalid parallel metadata.
pending_signal_count and payload_size_bytes at signal intake: WorkflowStub signal paths (guardPendingSignals) and recordAcceptedSignal (guardPayloadSize).
payload_size_bytes on an activity's successful result: ActivityOutcomeRecorder.
Not reached by external-worker commands
pending_activity_count, pending_child_count, pending_timer_count, history_transaction_size and search_attribute_size_bytes, along with the payload size of scheduled activity or child arguments, continue-as-new arguments and workflow output, are checked only in WorkflowExecutor and the local-activity paths. Those run PHP workflow code in-process. DefaultWorkflowTaskBridge::applyScheduleActivity and the other worker command handlers do not call them.
So the native work is the four enforced items above, not all ten limits. Each still needs a differential check against published PHP, for the refusal shape and the run's state afterwards.
Owner: Server for native limit parity; Workflow owns canonical embedded units. The opening memo-only status is stale as a source inventory: current native memo_limits/activity paths include pending signal/update counts and payload checks, while operator metrics expose several configured limits. Presence of those functions is not complete configured-boundary/artifact qualification.
Next is a per-limit table binding environment precedence, zero/negative behavior, unit, admission site, typed reason and real backend differential fixture. In particular, distinguish parallel metadata's fixed1000 bound from an honored configurable command limit and separate external-worker boundaries from in-process-only Core guards. General/Workflow: review any intentional divergence with central #228 before a new producer/setting is advertised. No boundary exception was removed here.
Core limit-unit source pointers requested in Server325/6643408164: public 2.20.3 StructuralLimits, StructuralLimitKind, StructuralLimitExceededException, unit boundary controls and feature controls. Retain the distinct pending counts, canonical serialized payload/value sizes, repeated encoded history bytes and logical write work; raw ingress, external blob size and operator totals are separate units. The accepted forward decisions are Workflow853/6643091946 (fixed hard cap plus tighter configured limit, identical admission carriers) and 930/6643088845 (Phase-B repeated logical work/accounting, bounded admission/cleanup). Those are source decisions, not an already shipped all-setting parity claim. Workflow owns the embedded source draft after #1030; Server owns its native per-setting/status/unit table and shared boundaries. No new resource run.
Delivery evidence remains the exact public Core 2.20.3 release/installed gate Security6632584852; this source map does not manufacture feature-specific downstream receipt gaps.
Closing: native enforces the PHP structural limits for signals, updates, activity results and command batches (message_streams.rs, updates.rs, execution.rs, completion_rules.rs). Open a narrow issue if a specific fixture differs.
Activity
rmcdaniel commentedon Oct 21, 2026
Scope from reading the published 2.5.14 image (
ghcr.io/durable-workflow/server@sha256:28fa0f39…), Workflow packagevendor/durable-workflow/workflow/src/V2:Enforced for external-worker deployments
memo_size_bytes:DefaultWorkflowTaskBridge(memo upserts). Native already enforces it.command_batch_size: only as the upper bound on a command'sparallel_group_sizemetadata (DefaultWorkflowTaskBridge::parallelMetadataEntry,WorkflowCommandNormalizer::parallelMetadataEntry). Larger metadata is treated as invalid parallel metadata.pending_signal_countandpayload_size_bytesat signal intake:WorkflowStubsignal paths (guardPendingSignals) andrecordAcceptedSignal(guardPayloadSize).pending_update_countandpayload_size_bytesat update intake:app/Support/ExternalWorkflowUpdateAdmission. Its refusal reason is the subject of Report update intake limits as structural_limit_exceeded in service mode #506.payload_size_byteson an activity's successful result:ActivityOutcomeRecorder.Not reached by external-worker commands
pending_activity_count,pending_child_count,pending_timer_count,history_transaction_sizeandsearch_attribute_size_bytes, along with the payload size of scheduled activity or child arguments, continue-as-new arguments and workflow output, are checked only inWorkflowExecutorand the local-activity paths. Those run PHP workflow code in-process.DefaultWorkflowTaskBridge::applyScheduleActivityand the other worker command handlers do not call them.So the native work is the four enforced items above, not all ten limits. Each still needs a differential check against published PHP, for the refusal shape and the run's state afterwards.
rmcdaniel commentedon Nov 4, 2026
Server open-item pass, 2026-11-04.
Owner: Server for native limit parity; Workflow owns canonical embedded units. The opening memo-only status is stale as a source inventory: current native memo_limits/activity paths include pending signal/update counts and payload checks, while operator metrics expose several configured limits. Presence of those functions is not complete configured-boundary/artifact qualification.
Next is a per-limit table binding environment precedence, zero/negative behavior, unit, admission site, typed reason and real backend differential fixture. In particular, distinguish parallel metadata's fixed1000 bound from an honored configurable command limit and separate external-worker boundaries from in-process-only Core guards. General/Workflow: review any intentional divergence with central #228 before a new producer/setting is advertised. No boundary exception was removed here.
rmcdaniel commentedon Nov 4, 2026
Core limit-unit source pointers requested in Server325/6643408164: public 2.20.3 StructuralLimits, StructuralLimitKind, StructuralLimitExceededException, unit boundary controls and feature controls. Retain the distinct pending counts, canonical serialized payload/value sizes, repeated encoded history bytes and logical write work; raw ingress, external blob size and operator totals are separate units. The accepted forward decisions are Workflow853/6643091946 (fixed hard cap plus tighter configured limit, identical admission carriers) and 930/6643088845 (Phase-B repeated logical work/accounting, bounded admission/cleanup). Those are source decisions, not an already shipped all-setting parity claim. Workflow owns the embedded source draft after #1030; Server owns its native per-setting/status/unit table and shared boundaries. No new resource run.
Delivery evidence remains the exact public Core 2.20.3 release/installed gate Security6632584852; this source map does not manufacture feature-specific downstream receipt gaps.
rmcdaniel commentedon Nov 11, 2026
Closing: native enforces the PHP structural limits for signals, updates, activity results and command batches (message_streams.rs, updates.rs, execution.rs, completion_rules.rs). Open a narrow issue if a specific fixture differs.