> This page location: Backend > Object Storage > Guides > Buckets
> Full Neon documentation index: https://neon.com/docs/llms.txt

> Summary: Neon Storage buckets hold your objects and branch with your database. Create buckets via the Neon Console, the Neon API, or the S3 API. Set the access level to private or public_read to control who can read objects.

# Buckets

Create and manage storage buckets

**Coming Soon: Private Preview**

This feature is in private preview: it's not ready for production use, and it may be briefly unavailable as we deploy updates. To get access, [sign up here](https://neon.com/blog/were-building-backends#access).

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

## 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 **Storage** tab. Click **New bucket**, enter a name, choose an access level, and click **Create**.

**neonctl**

```bash
neonctl bucket create my-bucket
```

**Neon API**

```bash
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**

```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**

```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')
```

**AWS CLI**

```bash
aws s3api create-bucket \
  --bucket my-bucket \
  --region us-east-2 \
  --endpoint-url "$AWS_ENDPOINT_URL_S3"
```

To create a `public_read` bucket with neonctl:

```bash
neonctl bucket create my-public-bucket --access-level public_read
```

**Note:** `AWS_ENDPOINT_URL_S3` is your branch's storage endpoint. See [Get started](https://neon.com/docs/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 **Storage** tab in the Console.

**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

**neonctl**

```bash
neonctl bucket list
```

**TypeScript**

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

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

**Python**

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

**AWS CLI**

```bash
aws s3api list-buckets --endpoint-url "$AWS_ENDPOINT_URL_S3"
```

## Delete a bucket

Buckets must be empty before deletion. [Delete all objects](https://neon.com/docs/storage/objects#delete-objects) first, then delete the bucket.

**neonctl**

```bash
neonctl bucket delete my-bucket
```

**TypeScript**

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

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

**Python**

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

**AWS CLI**

```bash
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 at the point of forking. No data is copied. From that point on:

- Creating or deleting a bucket on a child branch does not affect the parent.
- Objects uploaded to a child branch are only visible on that branch and its descendants.
- 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](https://neon.com/docs/storage/objects): upload, download, list, and delete objects
- [Authentication](https://neon.com/docs/storage/authentication): credential scopes and branch binding

---

## Related docs (Guides)

- [Objects](https://neon.com/docs/storage/objects)
- [Authentication](https://neon.com/docs/storage/authentication)
