Learn about code storage as it relates to execution of deployments
When a deployment runs, the execution environment needs access to the flow code.
Flow code is not stored directly in Prefect server or Prefect Cloud; instead, it must be made available to the execution environment. There are two main ways to achieve this:
Retrieve code from storage at runtime: The worker pulls code from a specified location before starting the flow run.
This page focuses on the second approach: retrieving code from a storage location at runtime.You have several options for where your code can be stored and pulled from:
The ideal choice depends on your team’s needs and tools.In the examples below, we show how to create a deployment configured to run on dynamic infrastructure for each of these storage options.
When using .deploy, specify a storage location for your flow with the flow.from_source method.
The source is either a URL to a git repository or a storage object. For example:
A local directory: source=Path(__file__).parent or source="/path/to/file"
A URL to a git repository: source="https://github.com/org/my-repo.git"
A storage object: source=GitRepository(url="https://github.com/org/my-repo.git")
The entrypoint is either the path to the file and the function name separated by a colon (for example, my_flow.py:my_func), or a Python module path (for example, my_module.my_flow.my_func).
Whether you use from_source or prefect.yaml to specify the storage location for your flow code, the resulting deployment will have a set of pull steps that your worker will use to retrieve the flow code at runtime.
If using a Process work pool, you can use one of the remote code storage options shown above, or you can store your flow code in a local folder.Here is an example of how to create a deployment with flow code stored locally:
from prefect import flowfrom pathlib import Path@flow(log_prints=True)def my_flow(name: str = "World"): print(f"Hello {name}!")if __name__ == "__main__": my_flow.from_source( source=str(Path(__file__).parent), # code stored in local directory entrypoint="local_process_deploy_local_code.py:my_flow", ).deploy( name="local-process-deploy-local-code", work_pool_name="my-process-pool", )
For a public repository, you can use the repository URL directly.If you are using a private repository and are authenticated in your environment at deployment creation and deployment execution, you can use the repository URL directly.Alternatively, for a private repository, you can create a Secret block or git-platform-specific credentials block to store your credentials:
Then you can reference this block in the Python deploy method or the prefect.yaml file pull step.If using the Python deploy method with a private repository that references a block, provide a GitRepository object instead of a URL, as shown below.
# relevant section of the file:pull: - prefect.deployments.steps.git_clone: repository: https://gitlab.com/org/my-repo.git # Uncomment the following line if using a credentials block # credentials: "{{ prefect.blocks.github-credentials.my-github-credentials-block }}" # Uncomment the following line if using a Secret block # access_token: "{{ prefect.blocks.secret.my-block-name }}"
Personal Access Token PermissionsWhen using a fine-grained token, ensure to add permissions to the token prior to saving. Per least privilege, we recommend granting the token the ability to read Contents and Metadata for your repository.
If using a Secret block, you can create it through code or the UI ahead of time and reference it at deployment creation as shown above.If using a GitHubCredentials block to store your credentials, you can create it ahead of time and reference it at deployment creation.
Install prefect-github with pip install -U prefect-github
Register all block types defined in prefect-github with prefect block register -m prefect_github
Create a GitHubCredentials block through code or the Prefect UI and reference it at deployment creation as shown above.
# relevant section of the file:pull: - prefect.deployments.steps.git_clone: repository: https://bitbucket.org/org/my-private-repo.git # Uncomment the following line if using a credentials block # credentials: "{{ prefect.blocks.bitbucket-credentials.my-bitbucket-credentials-block }}" # Uncomment the following line if using a Secret block # access_token: "{{ prefect.blocks.secret.my-block-name }}"
For accessing a private repository, we recommend using HTTPS with Repository, Project, or Workspace Access Tokens.Create a token with read access to the repository.Bitbucket requires you prepend the token string with x-token-auth: The full string looks like this: x-token-auth:abc_123_this_is_a_token.If using a Secret block, you can create it through code or the UI ahead of time and reference it at deployment creation as shown above.If using a BitBucketCredentials block to store your credentials, you can create it ahead of time and reference it at deployment creation.
Install prefect-bitbucket with pip install -U prefect-bitbucket
Register all block types defined in prefect-bitbucket with prefect block register -m prefect_bitbucket
Create a BitBucketCredentials block in code or the Prefect UI and reference at deployment creation as shown above.
# relevant section of the file:pull: - prefect.deployments.steps.git_clone: repository: https://gitlab.com/org/my-private-repo.git # Uncomment the following line if using a credentials block # credentials: "{{ prefect.blocks.gitlab-credentials.my-gitlab-credentials-block }}" # Uncomment the following line if using a Secret block # access_token: "{{ prefect.blocks.secret.my-block-name }}"
For accessing a private repository, we recommend using HTTPS with Project Access Tokens.Create a token with the read_repository and api scopes.If using a Secret block, you can create it through code or the UI ahead of time and reference it at deployment creation as shown above.If using a GitLabCredentials block to store your credentials, you can create it ahead of time and reference it at deployment creation.
Install prefect-gitlab with pip install -U prefect-gitlab
Register all block types defined in prefect-gitlab with prefect block register -m prefect_gitlab
Create a GitLabCredentials block in code or the Prefect UI and reference it at deployment creation as shown above.
Note that you can specify a branch if creating a GitRepository object.
The default is "main".
Push your codeWhen you make a change to your code, Prefect does not push your code to your git-based version control platform.
This is intentional to avoid confusion about the git history and push process.
If you use Prefect Cloud, you can install the Prefect Cloud GitHub App to authenticate
to GitHub at runtime and pull private repository code without storing long-lived credentials.This approach is recommended for GitHub.com organizations that enforce SAML/SSO
(GitHub Enterprise Cloud), because it removes the need for Personal Access Tokens (PATs)
that must be individually
authorized for SAML.
Instead, an organization owner installs the GitHub App once, and every deployment in the
organization can pull code through it.
This integration works with GitHub.com and GitHub Enterprise Cloud. It is not compatible
with GitHub Enterprise Server (self-hosted) installations.
An organization owner installs the app and grants it access to selected repositories.
At deployment runtime, the worker calls prefect-cloud github token to request a
short-lived installation access token from Prefect Cloud.
Prefect Cloud exchanges its credentials with GitHub to generate the token, scoped only
to the repositories the app can access.
The worker uses this token to clone the repository, then the token expires.
Because the GitHub App is authorized at the organization level, it inherits SAML/SSO
authorization automatically. Individual users do not need to authorize tokens through
your identity provider.
Read-only access to repository contents, limited to repositories selected during app installation
Credential storage
No customer credentials or long-lived tokens are stored in your deployment configuration. Prefect Cloud holds the GitHub App’s private key to mint installation tokens on your behalf.
SAML/SSO compatibility
The GitHub App is authorized at the organization level, bypassing the per-user SAML token authorization requirement
Revocation
An organization owner can uninstall the app or change repository access at any time from GitHub App settings
Navigate to the Prefect Cloud GitHub App installation page
and select the GitHub organization and repositories you want to grant access to.If your organization enforces SAML/SSO, an organization owner must approve the app
installation. The app is then authorized for SAML access automatically.
2
Configure your deployment
Add the following pull steps to your prefect.yaml file. Replace owner/repository
with your repository’s full name:
The prefect-cloud github token command requires that the worker’s environment is
authenticated to Prefect Cloud. Ensure that PREFECT_API_KEY and PREFECT_API_URL are
set in the worker’s environment, or that the worker is logged in through prefect cloud login.
For organizations that require PAT-based access instead, see the GitHub tab
earlier on this page. If you use SSO more broadly with Prefect Cloud, see
Configure single sign-on.
Another popular flow code storage option is to include it in a Docker image.
All work pool options except Process and Prefect Managed allow you to bake your code into a Docker image.To create a deployment with Docker-based flow code storage use the Python deploy method or create a prefect.yaml file.
If you use the Python deploy method to store the flow code in a Docker image, you don’t need to use the from_source method.
The prefect.yaml file below was generated by running prefect deploy from the CLI (a few lines of metadata were excluded from the top of the file output for brevity).Note that the build section is necessary if baking your flow code into a Docker image.
from prefect import flow@flowdef my_flow(): print("Hello from inside a Docker container!")if __name__ == "__main__": my_flow.deploy( name="my-docker-deploy", work_pool_name="my_pool", image="my-docker-image:latest", push=False )
# build section allows you to manage and build docker imagesbuild:- prefect_docker.deployments.steps.build_docker_image: requires: prefect-docker>=0.6.1 id: build-image dockerfile: auto image_name: my-registry/my-image tag: latest# push section allows you to manage if and how this project is uploaded to remote locationspush: null# pull section allows you to provide instructions for cloning this project in remote locationspull:- prefect.deployments.steps.set_working_directory: directory: /opt/prefect/my_directory# the deployments section allows you to provide configuration for deploying flowsdeployments:- name: my-docker-deployment entrypoint: my_file.py:my_flow work_pool: name: my_pool job_variables: image: '{{ build-image.image }}'
By default, .deploy will build a Docker image that includes your flow code and any pip packages specified in a requirements.txt file.In the examples above, we elected not to push the resulting image to a remote registry.To push the image to a remote registry, pass push=True in the Python deploy method or add a push_docker_image step to the push section of the prefect.yaml file.
If an image is not specified by one of the methods above, deployment flow runs associated with a Docker work pool will use the base Prefect image (e.g. prefecthq/prefect:3-latest) when executing.
Alternatively, you can create a custom Docker image outside of Prefect by running docker build && docker push elsewhere (e.g. in your CI/CD pipeline) and then reference the resulting image in the job_variables section of your deployment definition, or set the image as a default directly on the work pool.
When you run prefect deploy with a custom image in job_variables and no build step, Prefect automatically adds a set_working_directory pull step to your deployment. In interactive mode, Prefect prompts you for the working directory inside your image (defaulting to /opt/prefect/<project-dir>). In non-interactive mode, it defaults to /opt/prefect and prints a warning. To use a different path, add an explicit set_working_directory step to the pull section of your prefect.yaml.
When a deployment pulls code that includes a pyproject.toml, Prefect starts the flow run without installing project
dependencies by default. This keeps custom images predictable and avoids unexpected package installation during flow run
startup.If you want Prefect to prepare the project’s runtime dependencies before starting the flow run, set
PREFECT_RUNNER_AUTO_INSTALL_DEPENDENCIES=true in the image or work pool job variables. Default dependency groups are not
installed.
Setting PREFECT_RUNNER_AUTO_INSTALL_DEPENDENCIES=true is necessary but not sufficient. Prefect only
uses uv to install dependencies at runtime when all of the following conditions are met:
PREFECT_RUNNER_AUTO_INSTALL_DEPENDENCIES is set to true.
A pyproject.toml exists at the detected project root.
The dependencies list under [project] in that pyproject.toml includes prefect.
uv is available on the runtime environment’s PATH.
If any condition is not met, Prefect silently falls back to running the flow without installing
dependencies. Verify each condition when debugging missing packages at runtime.
If your custom image already contains the required project code and dependencies, leave
PREFECT_RUNNER_AUTO_INSTALL_DEPENDENCIES unset or set it to false.For more information, see this discussion of custom Docker images.
Another option for flow code storage is any fsspec-supported storage location, such as AWS S3, Azure Blob Storage, or GCP GCS.If the storage location is publicly available, or if you are authenticated in the environment where you are creating and running your deployment, you can reference the storage location directly.
You don’t need to pass credentials explicitly.To pass credentials explicitly to authenticate to your storage location, you can use either of the following block types:
Prefect integration library storage blocks, such as the prefect-aws library’s S3Bucket block, which can use a AWSCredentials block when it is created.
Secret blocks
If you use a storage block such as the S3Bucket block, you need to have the prefect-aws library available in the environment where your flow code runs.You can do any of the following to make the library available:
Install the library into the execution environment directly
Specify the library in the work pool’s Base Job Template in the Environment Variables section like this:{"EXTRA_PIP_PACKAGES":"prefect-aws"}
Specify the library in the environment variables of the deploy method as shown in the examples below
Specify the library in a requirements.txt file and reference the file in the pull step of the prefect.yaml file like this:
The examples below show how to create a deployment with flow code in a cloud provider storage location.
For each example, we show how to access code that is publicly available.
The prefect.yaml example includes an additional line to reference a credentials block if authenticating to a private storage location through that option.We also include Python code that shows how to use an existing storage block and an example of that creates, but doesn’t save, a storage block that references an existing nested credentials block.
Install the prefect-aws library with pip install -U prefect-aws
Register the blocks in prefect-aws with prefect block register -m prefect_aws
Create a user with a role with read and write permissions to access the bucket. If using the UI, create an access key pair with IAM -> Users -> Security credentials -> Access keys -> Create access key. Choose Use case -> Other and then copy the Access key and Secret access key values.
Create an AWSCredentials block in code or the Prefect UI. In addition to the block name, most users will fill in the AWS Access Key ID and AWS Access Key Secret fields.
Install the prefect-azure library with pip install -U prefect-azure
Register the blocks in prefect-azure with prefect block register -m prefect_azure
Create an access key for a role with sufficient (read and write) permissions to access the blob.
You can create a connection string containing all required information in the UI under Storage Account -> Access keys.
Create an Azure Blob Storage Credentials block in code or the Prefect UI. Enter a name for the block and paste the
connection string into the Connection String field.
Install the prefect-gcp library with pip install -U prefect-gcp
Register the blocks in prefect-gcp with prefect block register -m prefect_gcp
Create a service account in GCP for a role with read and write permissions to access the bucket contents.
If using the GCP console, go to IAM & Admin -> Service accounts -> Create service account.
After choosing a role with the required permissions,
see your service account and click on the three dot menu in the Actions column.
Select Manage Keys -> ADD KEY -> Create new key -> JSON. Download the JSON file.
Create a GCP Credentials block in code or the Prefect UI. Enter a name for the block and paste the entire contents of the JSON key file into the Service Account Info field.
Reference the block as shown above.
Another authentication option is to give the worker access to the storage location at runtime through SSH keys.