Mat Partridge
05/21/2026, 9:22 AMMarvin
05/21/2026, 9:22 AMMarvin
05/21/2026, 9:24 AM.fn during local dev.
Example:
python
from prefect import flow
from prefect_aws.decorators import ecs
@ecs(work_pool="my-ecs-pool")
@flow
def my_flow(x: int):
return x * 2
# Local dev: runs locally, no ECS submission
result = my_flow.fn(5)
# Normal call: submits to ECS via the work pool
result = my_flow(5)
A few important notes:
* @ecs changes the flow so that calling my_flow(...) submits it to ECS
* There is not a built-in “run locally instead” switch for the decorator
* So for local execution, .fn(...) is the simplest override
If you want the same call site to behave differently in dev vs prod, a common pattern is to apply @ecs conditionally:
python
import os
from prefect import flow
from prefect_aws.decorators import ecs
def maybe_ecs(work_pool: str, **kwargs):
def decorator(fn):
wrapped = flow(fn)
if os.getenv("RUN_ON_ECS") == "true":
return ecs(work_pool=work_pool, **kwargs)(wrapped)
return wrapped
return decorator
@maybe_ecs(work_pool="my-ecs-pool")
def my_flow(x: int):
return x * 2
Then:
* local dev: python flow.py → runs locally
* prod: RUN_ON_ECS=true python flow.py → submits to ECS
Relevant docs/code:
* Prefect AWS integration docs: https://prefecthq.github.io/prefect-aws/
* Prefect deployments docs: https://docs.prefect.io/v3/how-to-guides/deployments
* Prefect source for infrastructure-bound flows: https://github.com/PrefectHQ/prefect
* Prefect AWS source: https://github.com/PrefectHQ/prefect/tree/main/src/integrations/prefect-aws
If you want, I can also show the best-practice dev/prod structure for ECS flows in Prefect 3.x.Mat Partridge
05/21/2026, 9:31 AMMarvin
05/21/2026, 9:31 AMMarvin
05/21/2026, 9:33 AMimportlib_metadata is a Python package backport. In modern Python, the stdlib module is importlib.metadata, but some dependencies in the container may still import importlib_metadata. If that package is missing in the ECS image, you’ll get:
text
ModuleNotFoundError: No module named 'importlib_metadata'
Why this happens:
* your local environment has the full dependency set installed
* the ECS image/task is using a different environment
* a transitive dependency in the ECS container expects importlib_metadata
* this is commonly caused by a custom Docker image or incomplete dependency install
What to check first
1. Are you using an official Prefect AWS image or a custom one?
* Official images are the safest: prefecthq/prefect-aws:...
* Custom images often miss transitive deps
2. Are local and ECS using the same Python version?
* Python 3.12 tends to avoid some of this pain
* Python 3.10/3.11 environments hit this more often
3. Did your image actually install all runtime dependencies?
Make sure the image build installs prefect and prefect-aws fully.
Example Dockerfile:
dockerfile
FROM prefecthq/prefect:3-latest-python3.12
RUN pip install --no-cache-dir prefect-aws
Or if you’re starting from plain Python:
dockerfile
FROM python:3.12-slim
RUN pip install --no-cache-dir "prefect[aws]" prefect-aws
If you want the fastest tactical fix, explicitly install the missing package too:
dockerfile
RUN pip install --no-cache-dir "prefect[aws]" prefect-aws importlib-metadata
That said, I’d treat that as a signal that your ECS image is not matching your local env.
Recommended fix
* use a pinned official image if possible, like prefecthq/prefect-aws:<tag>
* or rebuild your custom image so it installs all runtime deps
* align Python versions between local and ECS
* avoid relying on latest in production
Why it deploys to ECS when you run locally
Because with @ecs, calling the flow normally submits it to the ECS work pool. For local-only execution, use:
python
my_flow.fn(...)
instead of:
python
my_flow(...)
So if you were expecting a local run but called the decorated flow normally, that explains why you’re seeing an ECS-container import error.
Helpful links:
* Prefect AWS integration: https://prefecthq.github.io/prefect-aws/
* Deployments docs: https://docs.prefect.io/v3/how-to-guides/deployments
* Prefect repo: https://github.com/PrefectHQ/prefect
If you paste your Docker image / deployment config / ECS task image, I can help pinpoint exactly where importlib_metadata is being missed.