# Buckets

A bucket is a named container for objects in Neon Object Storage. Buckets are scoped to a branch and inherit from parent branches when a new branch is created. No data is copied on fork.

For object size and storage limits, see [Limits](/guides/object-storage-index#limits).

## Create a bucket

You can create a bucket from the Neon Console, the Neon CLI, the Neon API, or directly via the S3 API.

**Neon Console**

In the Neon Console, navigate to your project, select a branch, and open the **Object storage** tab. Click **New bucket**, enter a name, choose an access level, and click **Create**.

:::code-group
```bash title="neon"
neon buckets create my-bucket
```

```bash title="Neon API"
curl -X POST "https://console.neon.tech/api/v2/projects/{project_id}/branches/{branch_id}/buckets" \
  -H "Authorization: Bearer $NEON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-bucket", "access_level": "private"}'
```

```typescript title="TypeScript"
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';

const client = new S3Client({
  region: process.env.AWS_REGION,
  endpoint: process.env.AWS_ENDPOINT_URL_S3,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
  forcePathStyle: true,
});

await client.send(new CreateBucketCommand({ Bucket: 'my-bucket' }));
```

```python title="Python"
import boto3, os

client = boto3.client(
    's3',
    region_name=os.environ['AWS_REGION'],
    endpoint_url=os.environ['AWS_ENDPOINT_URL_S3'],
    aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
)

client.create_bucket(Bucket='my-bucket')
```

```bash title="AWS CLI"
aws s3api create-bucket \
  --bucket my-bucket \
  --region us-east-2 \
  --endpoint-url "$AWS_ENDPOINT_URL_S3"
```
:::

To create a `public_read` bucket with neon:

```bash
neon buckets create my-public-bucket --access-level public_read
```

:::callout{intent="note"}
`AWS_ENDPOINT_URL_S3` is your branch's storage endpoint. See [Get started](/guides/object-storage-get-started) for how to obtain it.
:::

## Access levels

Every bucket has an access level that controls who can read objects in it.

| Access level  | Reads                                 | Writes                     |
| ------------- | ------------------------------------- | -------------------------- |
| `private`     | Require a valid credential            | Require a valid credential |
| `public_read` | Open to anyone (no credential needed) | Require a valid credential |

The default is `private`. Set the access level when creating a bucket via the Neon API, or change it from the **Object storage** tab in the Console.

:::callout{intent="note"}
Access level is set through the Neon Console or API, not through the S3 API. S3 ACL and bucket policy mutation requests (PutBucketAcl, PutBucketPolicy) return `501 Not Implemented`. If you need to change access level on an existing bucket, use the Console or Neon API.
:::

**public\_read example**

Objects in a `public_read` bucket are accessible at:

```
https://<branch-id>.storage.c-<N>.us-east-2.aws.neon.tech/my-public-bucket/<object-key>
```

## List buckets

:::code-group
```bash title="neon"
neon buckets list
```

```typescript title="TypeScript"
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';

const { Buckets } = await client.send(new ListBucketsCommand({}));
console.log(Buckets);
```

```python title="Python"
response = client.list_buckets()
print(response['Buckets'])
```

```bash title="AWS CLI"
aws s3api list-buckets --endpoint-url "$AWS_ENDPOINT_URL_S3"
```
:::

## Delete a bucket

Buckets must be empty before deletion. [Delete all objects](/guides/object-storage-objects#delete-objects) first, then delete the bucket.

:::code-group
```bash title="neon"
neon buckets delete my-bucket
```

```typescript title="TypeScript"
import { S3Client, DeleteBucketCommand } from '@aws-sdk/client-s3';

await client.send(new DeleteBucketCommand({ Bucket: 'my-bucket' }));
```

```python title="Python"
client.delete_bucket(Bucket='my-bucket')
```

```bash title="AWS CLI"
aws s3api delete-bucket \
  --bucket my-bucket \
  --endpoint-url "$AWS_ENDPOINT_URL_S3"
```
:::

## Bucket branching

When you create a new branch, it inherits all buckets from its parent, including the objects already in them at the moment of forking — the same copy-on-write model Neon uses for branching Postgres data, so nothing is duplicated upfront. From that point on:

- Creating or deleting a bucket on a child branch does not affect the parent.
- New uploads, overwrites, and deletes on a child branch are only visible on that branch and its descendants, even for objects that existed at fork time.
- The parent branch continues to see its own state unchanged.

This makes it safe to test bucket changes in a preview branch without affecting production.

## Next steps

- [Objects](/guides/object-storage-objects): upload, download, list, and delete objects
- [Authentication](/guides/object-storage-authentication): credential scopes and branch binding
- [Limits](/guides/object-storage-index#limits): object size and usage limits

## Need help?

Join our [Discord Server](https://neon.com/discord) to ask questions or see what others are doing with Neon. For paid plan support options, see [Support](/guides/postgres-introduction-support).

## Related pages

- [Objects](./object-storage-objects.md)
- [Object storage authentication](./object-storage-authentication.md)
- [Object storage logs](./object-storage-logs.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
