# Storage Options

Prefect natively has various different Storage options built in that can be used for saving Flows to different systems.

As of Prefect version `0.9.0` every storage option except for `Docker` will automatically have a Result Handler attached which will write results to the corresponding platform. For example, this means that if you register a flow to Prefect Cloud with the `S3` storage option then the flow's results will also be written to the same S3 bucket through the use of the [S3 Result Handler](/api/latest/engine/result_handlers.html#s3resulthandler).

## Local

[Local Storage](/api/latest/environments/storage.html#local) is the default Storage options for all Flows. This stores the Flow as bytes in the local filesystem which means it can only be run by a [Local Agent](/cloud/agents/local.html) running on the same machine.

```python
from prefect import Flow
from prefect.environments.storage import Local

flow = Flow("local-flow", storage=Local())

storage.build()
```

The Flow is now available under `~/.prefect/flows/local-flow.prefect`.

::: tip Sensible Defaults
Flows registered with this Storage option will automatically be labeled with the hostname of the machine from which it was registered; this prevents Agents not running on the same machine from attempting to run this flow.

Additionally, in more recent releases of Core your Flow will default to using a `LocalResultHandler` for persisting any task results in the same file location.
:::

## Azure Blob Storage

[Azure Storage](/api/latest/environments/storage.html#azure) is a Storage option which uploads Flows to an Azure Blob container. Currently Flows stored using this option can only be run by [Local Agents](/cloud/agents/local.html) as long as the machine running the Local Agent is configured to download from that Azure Blob container using a connection string.

```python
from prefect import Flow
from prefect.environments.storage import Azure

flow = Flow("azure-flow", storage=Azure(container="<my-container>", connection_string="<my-connection-string>"))

storage.build()
```

The Flow is now available in the container under `azure-flow/slugified-current-timestamp`.

::: tip Sensible Defaults
Flows registered with this Storage option will automatically be labeled with `"azure-flow-storage"`; this prevents Agents not explicitly authenticated with your Azure deployment from attempting to run this flow.

Additionally, in more recent releases of Core your Flow will default to using a `AzureResultHandler` for persisting any task results in the same Azure container.
:::

:::tip Azure Credentials
Azure Storage uses an Azure [connection string](https://docs.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string) which means both upload (build) and download (Local Agent) times need to have a working Azure connection string. Azure Storage will also look in the environment variable `AZURE_STORAGE_CONNECTION_STRING` if it is not passed to the class directly.
:::

## AWS S3

[S3 Storage](/api/latest/environments/storage.html#s3) is a Storage option which uploads Flows to an AWS S3 bucket. Currently Flows stored using this option can only be run by [Local Agents](/cloud/agents/local.html) as long as the machine running the Local Agent is configured to download from an S3 bucket.

```python
from prefect import Flow
from prefect.environments.storage import S3

flow = Flow("s3-flow", storage=S3(bucket="<my-bucket>"))

storage.build()
```

The Flow is now available in the bucket under `s3-flow/slugified-current-timestamp`.

::: tip Sensible Defaults
Flows registered with this Storage option will automatically be labeled with `"s3-flow-storage"`; this helps prevent Agents not explicitly authenticated with your AWS deployment from attempting to run this flow.

Additionally, in more recent releases of Core your Flow will default to using a `S3ResultHandler` for persisting any task results in the same S3 bucket.
:::

:::tip AWS Credentials
S3 Storage uses AWS credentials the same way as [boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html) which means both upload (build) and download (Local Agent) times need to have proper AWS credential configuration.
:::

## Google Cloud Storage

[GCS Storage](/api/latest/environments/storage.html#gcs) is a Storage option which uploads Flows to a Google Cloud Storage bucket. Currently Flows stored using this option can only be run by [Local Agents](/cloud/agents/local.html) as long as the machine running the Local Agent is configured to download from a GCS bucket.

```python
from prefect import Flow
from prefect.environments.storage import GCS

flow = Flow("gcs-flow", storage=GCS(bucket="<my-bucket>"))

storage.build()
```

The Flow is now available in the bucket under `gcs-flow/slugified-current-timestamp`.

::: tip Sensible Defaults
Flows registered with this Storage option will automatically be labeled with `"gcs-flow-storage"`; this helps prevents Agents not explicitly authenticated with your GCS project from attempting to run this flow.

Additionally, in more recent releases of Core your Flow will default to using a `GCSResultHandler` for persisting any task results in the same GCS location.
:::

:::tip Google Cloud Credentials
GCS Storage uses Google Cloud credentials the same way as the standard [google.cloud library](https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-python) which means both upload (build) and download (Local Agent) times need to have the proper Google Application Credentials configuration.
:::

## Docker

[Docker Storage](/api/latest/environments/storage.html#docker) is a Storage option which puts Flows inside of a Docker image and pushes them to a container registry. This method of Storage has the largest deployment compatability with the [Docker Agent](/cloud/agents/docker.html), [Kubernetes Agent](/cloud/agents/kubernetes.html), and [Fargate Agent](/cloud/agents/fargate.html).

```python
from prefect import Flow
from prefect.environments.storage import Docker

flow = Flow("gcs-flow", storage=Docker(registry_url="<my-registry.io>", image_name="my_flow"))

storage.build()
```

The Flow is now available in the container registry under `my-registry.io/my_flow:slugified-current-timestamp`. Note that each type of container registry uses a different format for image naming (e.g. DockerHub vs GCR).

If you do not specify a `registry_url` for your Docker Storage then the image will not attempt to be pushed to a container registry and instead the image will live only on your local machine. This is useful when using the Docker Agent because it will not need to perform a pull of the image since it already exists locally.

:::tip Container Registry Credentials
Docker Storage uses the [Docker SDK for Python](https://docker-py.readthedocs.io/en/stable/index.html) to build the image and push to a registry. Make sure you have the Docker daemon running locally and you are configured to push to your desired container registry. Additionally make sure whichever platform Agent deploys the container also has permissions to pull from that same registry.
:::
