Python SDK¶
Execution SDK¶
The execution SDK (aws-durable-execution-sdk-python) runs in your Lambda functions. It
provides DurableContext, operations, and decorators. Install it in your Lambda
deployment package.
Testing SDK¶
The testing SDK (aws-durable-execution-sdk-python-testing) lets you test durable
functions locally without AWS. It provides DurableFunctionTestRunner, pytest
integration, and result inspection. Install it in your development environment only.
Decorators¶
The SDK provides decorators to mark functions as durable:
@durable_executionmarks your Lambda handler as a durable function.@durable_stepwraps a function so it can be passed tocontext.step(), binding any extra arguments and preserving the function name.@durable_with_child_contextwraps a function that receives a childDurableContext, for use withcontext.run_in_child_context().@durable_parallel_branchwraps a function into a namedParallelBranchforcontext.parallel(). Call it with an optionalnameto produce the decorator.@durable_wait_for_callbackwraps a submitter function forcontext.wait_for_callback(), binding extra arguments alongside thecallback_idandWaitForCallbackContext.
The Python SDK uses synchronous methods and does not support await.
Upgrade from 2.x to 3.0¶
Core 3.0 creates a fresh instrumentation plugin for each Lambda invocation. This isolates
plugin state when invocations run concurrently. The release also changes operation
subtypes to strings and preserves None results in BatchResult. Review those changes
even if your application uses no plugins.
Upgrade dependencies together¶
The Core 3.0 and OTel 2.0 release is available on PyPI and requires Python 3.11 or later. Use these compatible released versions:
| Package | Version |
|---|---|
aws-durable-execution-sdk-python |
3.0.0 |
aws-durable-execution-sdk-python-otel |
2.0.0 |
aws-durable-execution-sdk-python-testing |
1.4.0 |
aws-durable-execution-sdk-python-telemetry-exporter |
1.0.0 |
Upgrade Core and OTel together in your requirements, lock file, deployment bundle, and
Lambda layers. OTel remains optional, but OTel 2 requires Core >=3.0.0,<4. Testing SDK
1.4.0 requires Core 3 and supports custom subtypes; earlier testing releases cannot load
them. If you use the optional Telemetry Exporter, upgrade it to the stable
1.0.0 release.
It requires Core >=3.0.0,<4; version 0.0.1 uses the Core 2 plugin contract. Run
python -m pip check in the built application environment.
The base OTel package uses the OpenTelemetry distribution supplied by your ADOT or
community layer. If your application configures its own provider, install
aws-durable-execution-sdk-python-otel[standalone]==2.0.0 and configure the provider and
exporter. Installing the extra alone does not export traces.
Update plugin registrations¶
Replace plugin instances in plugins with factory objects. Each factory's synchronous
create_plugin(info) method must return a fresh DurableInstrumentationPlugin subclass
instance. Pass a factory instance, not a bare lambda or an uninstantiated factory class
with an ordinary instance method. Keep shared resources on the factory and invocation
state on the plugin.
Replace InvocationOtelPlugin(...) with InvocationOtelPluginFactory(...), or
ExecutionOtelPlugin(...) with ExecutionOtelPluginFactory(...). Choose one OTel view
across the decorator and DURABLE_EXECUTION_PLUGINS.
Replace the removed DurableInstrumentationPluginProvider wrapper with a factory
object. Update the distribution's aws_durable_execution.plugins entry point to name
that object, then rebuild and reinstall the provider package or layer.
The Telemetry Exporter's durable_execution_telemetry(config) helper now returns a
factory. Pass its result directly to plugins.
Review subtype and batch-result changes¶
Read sub_type as str | None. Replace .value reads with the string itself and is
comparisons with ==. Import OperationSubType from
aws_durable_execution_sdk_python.lambda_service; the plugin module no longer
re-exports it.
StepConfig and CallbackConfig accept a keyword-only sub_type, and
ChildConfig.sub_type accepts custom strings. A custom subtype must contain 1 to 32
ASCII letters, digits, hyphens, or underscores. Preserve its value for executions already in
flight because replay compares it with the checkpoint. Testing SDK 1.4.0 does not yet
validate invalid subtypes locally, so verify custom subtypes in cloud tests too.
BatchResult.succeeded() and get_results() now retain every successful branch,
including results equal to None. Update aggregations and assertions that assumed these
methods omitted None. failed() and get_errors() likewise retain every failed item.
Update custom operation hooks¶
Hooks no longer run on the checkpoint thread. Each hook still runs synchronously on its
own calling thread, and a slow hook delays that thread. on_operation_change runs on a
dedicated thread and can combine several checkpoint responses into one notification.
Do not assume one callback per response or ordering across threads. Synchronize state
shared between hooks, and finish plugin-owned background work in on_invocation_end.
Validate the upgrade¶
Check the package versions imported by the deployed function and its layers. Test a
workflow that suspends and resumes, then test concurrent invocations and parallel
branches, including branches that return None or fail. Confirm fresh plugin instances
and telemetry for successful, failed, and retried invocations. Plugin fields do not
survive suspension, and shared resources still need synchronization. Preserve operation
names, types, subtypes, order, nesting, and serialization while executions remain in
flight, and verify completed steps do not repeat their side effects on replay.
For all API changes and before/after examples, see the Python 2.x to 3.0 migration guide.
2.x Upgrade¶
When upgrading from 1.x to 2.x, review the Python SDK migration guide in the
SDK repository.
The main changes are:
- Catch the typed, per-operation errors
StepError,InvokeError,ChildContextError, andWaitForConditionError(or the baseDurableOperationError) instead of the removedCallableRuntimeError. - Replace
except CallableRuntimeErrorafterBatchResult.throw_if_error()withChildContextError,SerDesError, andBatchCompletionError. - Catch serialization failures as
SerDesError(a direct child ofDurableExecutionsError) instead ofExecutionError. - Expect the first-run serialize/deserialize round trip for
step, child contexts,map/parallel, andwait_for_condition, and ensurewait_for_conditioninitial_stateis serializable by the configured serdes. - Read the new
attemptfield onStepContextandWaitForConditionCheckContext, and passattemptwhen constructing those contexts directly in tests.