Buckets
storage buckets file organization configuration file restrictionsBuckets are containers that organize files and group configuration. Each bucket can have its own size limits, cache settings, and pre-signed URL configuration. Buckets are stored in the storage.buckets table and are accessible through the GraphQL API.
Default Bucket
Section titled “Default Bucket”Every Nhost project includes a default bucket. When no bucket is specified during upload, files go into this bucket. The default bucket cannot be deleted.
Bucket Configuration
Section titled “Bucket Configuration”Each bucket supports the following settings:
| Setting | Description |
|---|---|
| Minimum file size | Reject files smaller than this value (bytes) |
| Maximum file size | Reject files larger than this value (bytes) |
| Cache control | HTTP Cache-Control header for files in this bucket |
| Pre-signed URLs enabled | Whether to allow pre-signed URL generation |
| Download expiration | Pre-signed URL expiration time (seconds) |
Creating Buckets
Section titled “Creating Buckets”You can create buckets by inserting rows into storage.buckets, either through the Nhost Dashboard or via a database migration.
Via the Dashboard:
- Navigate to Database
- Switch to the storage schema, then select the buckets table
- Click Insert and set the bucket
id(e.g.,avatars)
Via a migration:
INSERT INTO storage.buckets (id, max_upload_file_size, cache_control, presigned_urls_enabled, download_expiration)VALUES ('avatars', 5242880, 'public, max-age=3600', true, 300);Uploading to a Bucket
Section titled “Uploading to a Bucket”Specify the bucket-id field when uploading:
// Upload to a specific bucketconst response = await nhost.storage.uploadFiles({ 'bucket-id': 'avatars', 'file[]': [avatarFile],})
const uploadedFile = response.body.processedFiles?.[0]// Upload with custom metadataconst response = await nhost.storage.uploadFiles({ 'bucket-id': 'documents', 'file[]': [pdfFile], 'metadata[]': [{ name: 'quarterly-report.pdf', metadata: { department: 'finance', quarter: 'Q4-2024', }, }],})// Upload multiple files at onceconst response = await nhost.storage.uploadFiles({ 'bucket-id': 'photos', 'file[]': [photo1, photo2, photo3],})
for (const file of response.body.processedFiles ?? []) { console.log(`Uploaded: ${file.name} (${file.id})`)}# Upload to a specific bucketcurl -X POST \ -H "Authorization: Bearer $TOKEN" \ -F "bucket-id=avatars" \ -F "file[]=@avatar.jpg" \ https://local.storage.local.nhost.run/v1/files
# Upload with custom metadatacurl -X POST \ -H "Authorization: Bearer $TOKEN" \ -F "bucket-id=documents" \ -F "file[]=@report.pdf" \ -F 'metadata[]={"name":"quarterly-report.pdf","metadata":{"department":"finance","quarter":"Q4-2024"}}' \ https://local.storage.local.nhost.run/v1/files
# Upload multiple filescurl -X POST \ -H "Authorization: Bearer $TOKEN" \ -F "bucket-id=photos" \ -F "file[]=@photo1.jpg" \ -F "file[]=@photo2.jpg" \ https://local.storage.local.nhost.run/v1/filesQuerying Buckets
Section titled “Querying Buckets”query ListBuckets { buckets { id minUploadFileSize maxUploadFileSize cacheControl presignedUrlsEnabled downloadExpiration }}Common Patterns
Section titled “Common Patterns”User-scoped buckets — separate public and private content:
avatars— profile pictures, publicly accessiblepersonal— private user files, restricted to the owner
Content-type buckets — apply different size limits:
documents— PDFs, spreadsheets (larger max size)thumbnails— small images (smaller max size, aggressive caching)