Storage

A private S3-compatible bucket for uploads, generated files and backups.

A storage service is one private, S3-compatible bucket with its own access key. Use it for user uploads, generated files and backups. Files your app writes to its own disk are lost on every deploy, restart or crash, so anything you want to keep goes in a bucket.

A bucket uses none of your machines' memory, CPU or disk, and you can create one before the project has a machine.

Encryption

Every file is encrypted at rest with a key that belongs to this storage service alone. Your app reads and writes files as usual. Signed links and ranged downloads, such as video streaming, work the same.

Create a storage service

  1. On the project's Services page, click Add next to Storage.
  2. Fill in the form:
    • Name
    • Connect: the web services, workers and cron jobs that should get the S3_* variables. Shown when the project has any.
  3. Click Create storage service.

The form also shows the Price and the Region. The Overview shows Available when the bucket is ready.

Buckets are kept in EU-1. For a project outside the EU, your services reach the bucket over the internet.

Connect your services

Connecting a service adds these variables to it:

VariableValue
S3_ENDPOINTThe endpoint URL
S3_REGIONThe region to sign requests with
S3_BUCKETThe bucket name
S3_ACCESS_KEY_IDThe access key ID
S3_SECRET_ACCESS_KEYThe secret access key

To connect services later, open the storage service's Settings, choose services under Connect to your services, and click Update and redeploy. Turning a service off removes the variables and redeploys it.

The variables appear on the project's Environment page as managed variables. See Managed variables.

Connection details

Once the bucket is available, the Overview shows the Endpoint, Region, Bucket, Access key ID and Secret access key. Click the eye icon to show the secret. Addressing is Path-style.

You can use these details with any S3 client or tool, from your services or from your own computer.

Use it from code

Configure your S3 client with path-style addressing. Recent AWS SDKs also send checksums the endpoint doesn't support, so turn those off or uploads are rejected. In Python (boto3):

import os

import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url=os.environ["S3_ENDPOINT"],
    region_name=os.environ["S3_REGION"],
    aws_access_key_id=os.environ["S3_ACCESS_KEY_ID"],
    aws_secret_access_key=os.environ["S3_SECRET_ACCESS_KEY"],
    config=Config(
        s3={"addressing_style": "path"},
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
    ),
)

s3.put_object(Bucket=os.environ["S3_BUCKET"], Key="hello.txt", Body=b"hello")

Rename

In Settings, under General, change the Name and click Update. Only the name shown in the dashboard changes. The bucket name and access key stay the same.

Price

A storage service costs:

PartHow it's billed
Service feeA fixed monthly fee.
What it holdsPer GB a month, measured every hour.
What it sends outEverything read from the bucket, including by your own services, per GB at cost with no markup.

Uploads are free. The create form shows the prices under Price. The Overview shows what the bucket has Stored, its Price a month, and how much it has Downloaded this month.

Everything is billed by the second. The storage part keeps billing while the project is suspended, because the files still exist. See How billing works.

Delete a storage service

In Settings, under Danger Zone, click Delete storage service and confirm. This deletes the bucket and every object in it, and revokes its access key. The key its files were encrypted with is destroyed too. Connected services lose access. It can't be undone.