Starting in this release, for security reasons, Temporal Docker images have been slimmed down, and we have removed binaries and packages that do not strictly need to be included. This includes:
temporalio/admin-toolsRemoved tools:
bashpython3libevcurljqyqmysql-clientpostgresql-clientexpattinicqlshtctltctl-authorization-pluginAdded tools:
temporal-elasticsearch-tooltemporal cli still exists in the admin-tools image
temporalio/serverRemoved components:
temporal CLItctl and tctl-authorization-plugin (both deprecated)dockerizecurlbashdockerize → embedded sprigPrevious behavior:
dockerize processed a persistent config templatedockerize provided sprig + custom helper functionsNew behavior:
sprig templating is now built directly into the server binarydockerize is fully removed as an image dependencyTEMPORAL_SERVER_CONFIG_FILE_PATH is used to reference the config file. When not specified, the embedded template is processed.
# enable-template is required at the top of the config file to enable sprig templating.References:
The following images are deprecated and will no longer receive updates:
temporalio/auto-setup
temporalio/base-admin-toolstemporalio/base-servertemporalio/base-ci-buildertemporalio/base-builderDue to the Docker image breaking changes above, you must now use a minimum Helm chart version of temporal-0.73.2.
| Value | Description | Default |
|---|---|---|
server.useEntrypointScript | Use an entrypoint script that auto-detects dockerize vs sprig | false |
server.configMapsToMount | Which config template to mount: dockerize, sprig, or both | dockerize |
server.setConfigFilePath | Set TEMPORAL_SERVER_CONFIG_FILE_PATH env var (required for sprig) | false |
Option 1: Support both pre-1.30 and 1.30+ images (recommended for CI/testing)
server:
useEntrypointScript: true
configMapsToMount: "both"
setConfigFilePath: false
Option 2: 1.30+ only (sprig templating)
server:
image:
tag: "1.30.1" # or later
useEntrypointScript: false
configMapsToMount: "sprig"
setConfigFilePath: true
Option 3: Pre-1.30 only (dockerize, deprecated)
server:
image:
tag: "1.29.3" # or earlier
useEntrypointScript: false
configMapsToMount: "dockerize"
setConfigFilePath: false
PermissionDenied for Nexus operationsThe retry behavior for PermissionDenied errors when scheduling a Nexus operation has been updated.
PermissionDenied is now considered retryable.PermissionDenied errors.metrics.Tag interface-to-struct conversionmetrics.Tag is changing from an interface to a concrete type, and tag Key() and Value() reader methods are being replaced with exported Key and Value fields. metrics.Handler methods that accept tags now only accept the concrete type.
If you build your own temporal server with a custom metrics handler temporal.WithCustomMetricsHandler(metricsHandler), you need to update that handler to read metrics.Tag keys and values via exported Key and Value fields. If you provide a custom metrics.Tag interface implementation, you need to replace that implementation with a concrete metrics.Tag, for example by using metrics.StringTag.
system.enableCrossNamespaceCommands dynamic configuration valuesystem.enableCrossNamespaceCommands controls if a workflow can schedule a command to start childworkflow, cancel or signal another workflow in a different namespace. This feature is deprecated and the default value changed from true to false in this release. If your workload relying on this feature, please add an explicitly dynamic config override and set the value for this key to be true.
[!WARNING] Note — Worker Versioning users only If you are using the Worker Deployment API
SetWorkerDeploymentCurrentVersionand need to roll back after upgrading to v1.30.1, roll back to v1.29.3 or newer (not an older version). Rolling back to a version older than v1.29.3 after callingSetWorkerDeploymentCurrentVersionin v1.30.1 will cause a panic inListWorkerDeployments. To preserve this rollback safety guarantee, upgrade to v1.29.3 before upgrading to v1.30.1. If you are not using Worker Versioning, or not rolling back, this does not apply to you.
WorkerDeploymentInfo.RoutingConfigUpdateState == ROUTING_CONFIG_UPDATE_STATE_COMPLETED after SetCurrentVersion or SetRampingVersion API calls complete. Previously, those APIs returned success only after that condition was true, but now propagation completes asynchronously. In general, users need not be concerned with this change, but this behavior change is being noted for awareness.TemporalUsedWorkerVersions search attribute, which shows which Worker Deployment Versions a workflow has used during its lifetime.WorkflowExecutionOptionsUpdated history event now contains the identity of the client that changed the options (i.e., to set/unset a Versioning Override).LastCurrentTime timestamp in version info tells you whether a version was ever promoted to Current in the past. This enables accelerated rollout of versions that have been Current in the recent past by allowing the controller to detect whether a rollout is actually a rollback.1.29) are now in Public Preview.matching.useNewMatcher to true.matching.useNewMatcher, matching.enableFairness, and matching.enableMigration to true.Examples: Priority (task queue scoped)
matching.useNewMatcher:
- value: true
constraints:
namespace: "my-namespace"
taskQueueName: "my-task-queue"
Fairness (task queue scoped):
matching.useNewMatcher:
- value: true
constraints:
namespace: "my-namespace"
taskQueueName: "my-task-queue"
matching.enableFairness:
- value: true
constraints:
namespace: "my-namespace"
taskQueueName: "my-task-queue"
matching.enableMigration:
- value: true
constraints:
namespace: "my-namespace"
taskQueueName: "my-task-queue"
1.29:
UpdateWorkflowExecutionOptions and UpdateActivityOptions. Affected tasks are rescheduled.approximate_backlog_count metric now has a task_priority label.matching.priorityBacklogForwarding and matching.ephemeralDataUpdateInterval.matching.enableMigration is enabled before, or at the same time as, enabling fairness.matching.autoEnableV2.system.numConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute is a new dynamic config value to turn on degraded workflow visibility. Setting this to 0 turns off the feature entirely; any positive integer value becomes the number of consecutive workflow task failures needed to add the TemporalReportedProblems search attribute.TemporalReportedProblems is a new search attribute to identify workflows that are not making progress. The search attribute is a KeywordList with two entries: a cause and a category. The cause is either WorkflowTaskFailed or WorkflowTaskTimedOut. If the cause is WorkflowTaskFailed, the category is one of the following values. If the cause is WorkflowTaskTimedOut, the category is always ScheduleToClose.history.externalPayloadsEnabled is a new dynamic config value that enables server-side support for the claim-check pattern, where payloads are stored in external storage outside of history. When enabled, the server produces the aggregate size and count of external payloads and returns ExternalPayloadSizeBytes and ExternalPayloadCount on the DescribeWorkflowExecution call. This feature depends on claim-check pattern support in the Temporal SDK, which is currently under development.
Temporal can now run with OpenSearch 2+ as a visibility store. You only need to set up Temporal config as you would for Elasticsearch (see the provided Elasticsearch config template).
You can now change the maximum number of custom search attributes when using a SQL database as the visibility store. Previously, there was a hard-coded amount of pre-allocated fields that could be used to create custom search attributes. Now, you can change the maximum number of pre-allocated fields.
Example: assuming you have the default schema provided by Temporal and you want to increase the number of Int-type custom search attributes from 3 to 5 and Keyword-type from 10 to 12, follow the steps below:
Change your DB schema by adding the necessary columns.
MySQL (check the existing schema definition, and copy the syntax for the respective search attribute type):
ALTER TABLE custom_search_attributes
ADD COLUMN Int04 BIGINT GENERATED ALWAYS AS (search_attributes->"$.Int04"),
ADD COLUMN Int05 BIGINT GENERATED ALWAYS AS (search_attributes->"$.Int05"),
ADD COLUMN Keyword11 VARCHAR(255) GENERATED ALWAYS AS (search_attributes->>"$.Keyword11"),
ADD COLUMN Keyword12 VARCHAR(255) GENERATED ALWAYS AS (search_attributes->>"$.Keyword12");
ALTER TABLE custom_search_attributes
ADD INDEX by_int_04 ON custom_search_attributes (namespace_id, Int04),
ADD INDEX by_int_05 ON custom_search_attributes (namespace_id, Int05),
ADD INDEX by_keyword_11 ON custom_search_attributes (namespace_id, Keyword11),
ADD INDEX by_keyword_12 ON custom_search_attributes (namespace_id, Keyword12);
PostgreSQL (check the existing schema definition, and copy the syntax for the respective search attribute type):
ALTER TABLE executions_visibility
ADD COLUMN Int04 BIGINT GENERATED ALWAYS AS ((search_attributes->'Int04')::bigint),
ADD COLUMN Int05 BIGINT GENERATED ALWAYS AS ((search_attributes->'Int05')::bigint),
ADD COLUMN Keyword11 VARCHAR(255) GENERATED ALWAYS AS (search_attributes->>'Keyword11'),
ADD COLUMN Keyword12 VARCHAR(255) GENERATED ALWAYS AS (search_attributes->>'Keyword12');
ALTER TABLE executions_visibility
ADD INDEX by_int_04 ON executions_visibility (namespace_id, Int04, (COALESCE(close_time, '9999-12-31 23:59:59')) DESC, start_time DESC, run_id),
ADD INDEX by_int_05 ON executions_visibility (namespace_id, Int05, (COALESCE(close_time, '9999-12-31 23:59:59')) DESC, start_time DESC, run_id),
ADD INDEX by_keyword_11 ON executions_visibility (namespace_id, Keyword11, (COALESCE(close_time, '9999-12-31 23:59:59')) DESC, start_time DESC, run_id),
ADD INDEX by_keyword_12 ON executions_visibility (namespace_id, Keyword12, (COALESCE(close_time, '9999-12-31 23:59:59')) DESC, start_time DESC, run_id);
Modify the Temporal config file:
persistence:
visibilityStore: ...
visibility:
persistenceCustomSearchAttributes:
Int: 5
Keyword: 12
Restart Temporal.
You can only increase the maximum number of pre-allocated fields. Reducing the maximum number in the config is a no-op. Do not drop columns from your database table.
We are introducing a new experimental query converter to replace the existing ones. Currently, there are two query converter implementations: one for Elasticsearch, which builds the query search body; and one for SQL, which mainly validates the query. The new query converter unifies these implementations such that each Visibility Store implementation can implement the StoreQueryConverter interface to build its query object without needing to implement parsing and validation.
The new unified query converter is not 100% backward compatible with the existing query converter for Elasticsearch. In other words, if you use Elasticsearch as your visibility store, some queries might not work.
In particular, the new query converter performs stricter validation of query clauses and does not allow comparisons between a search attribute and a value of a different type. For example, the existing query converter for Elasticsearch allows comparing a Keyword-type search attribute with an integer (e.g., WorkflowType = 123), but the new query converter returns an error.
Since this is still experimental, the new unified query converter is disabled by default and can be enabled by setting the dynamic config system.visibilityEnableUnifiedQueryConverter: true. Once the new query converter is production-ready, it will be enabled by default (projected: v1.31.0), and the old ones will be deprecated and removed (projected: v1.32.0).
Temporal now provides an experimental temporal-elasticsearch-tool to manage visibility templates and indexes. The tool supports the same authentication and AWS request-signing features as the Temporal server. See the README for usage details.
This simplifies Nexus callback configuration by introducing internal routing for worker-targeted operations, eliminating the need for callback URL templates and allowlist configuration in normal deployments.
useSystemCallbackURL Toggle (component.nexusoperations.useSystemCallbackURL)temporal://system callback URL instead of requiring a configured URL templatefalse (will change to true in a future release)temporal://system Allowlistingtemporal://system URL is now always permitted by callback address validation, regardless of configured component.callbacks.allowedAddresses rulesBefore (required configuration):
system.enableNexus:
- value: true
component.nexusoperations.callback.endpoint.template:
- value: http://localhost:7233/namespaces/.NamespaceName/nexus/callback
component.callbacks.allowedAddresses:
- value:
- Pattern: "*"
AllowInsecure: true
After (zero config for worker targets):
system.enableNexus:
- value: true
component.nexusoperations.useSystemCallbackURL:
- value: true
When useSystemCallbackURL is enabled, your HTTPCallerProvider must route internal requests using the Source and Token headers, overriding the path to /nexus/callback. See components/callbacks/request.go for the routing implementation.
component.nexusoperations.limit.operation.timeout.min has been renamed to component.nexusoperations.limit.request.timeout.min, and given a default value of 500ms.component.nexusoperations.limit.dispatch.task.timeout.min, has been added with a default value of 1s. This is the minimum time remaining for a request to be dispatched to the handler worker. If the remaining request timeout is less than this value, a timeout error is returned. Working in conjunction with MinRequestTimeout, both configs help ensure that the server has enough time to complete a Nexus request.Temporal Docs Server Samples Server Helm Chart
Full Changelog: https://github.com/temporalio/temporal/compare/v1.30.0...v1.30.1
Fetched April 11, 2026