Storage
Volcano Storage provides durable object storage with RLS-style access control policies.
Volcano Storage provides durable object storage with RLS-style access control policies. Store user files, images, documents, and any binary data with automatic per-user isolation.
Features
| Feature | Description |
|---|---|
| Durable | Files are stored redundantly and served through the Volcano API |
| RLS policies | Fine-grained access control per object |
| Per-project | Each project has isolated storage namespaces |
| Buckets | Organize files into logical buckets |
| File limits | Set per-bucket file size and MIME type restrictions |
| SDK support | Full JavaScript/TypeScript SDK for browser and Node.js |
Quick example
Upload a file
import { VolcanoAuth } from '@volcano.dev/sdk';
const volcano = new VolcanoAuth({
apiUrl: 'https://api.yourapp.com',
anonKey: 'your-anon-key'
});
// Sign in first
await volcano.auth.signIn({ email: 'user@example.com', password: 'password' });
// Upload a file
const file = document.querySelector('input[type="file"]').files[0];
const { data, error } = await volcano.storage
.from('avatars')
.upload('profile.jpg', file);
if (error) {
console.error('Upload failed:', error.message);
} else {
console.log('Uploaded:', data.name);
}Download a file
const { data, error } = await volcano.storage
.from('avatars')
.download('profile.jpg');
if (!error) {
// data is a Blob
const url = URL.createObjectURL(data);
img.src = url;
}List files
const { data: files, error } = await volcano.storage
.from('documents')
.list('user/reports/');
files.forEach(file => {
console.log(`${file.name} - ${file.size} bytes`);
});Access control
Storage uses RLS-style policies to control access. By default, without policies, all access is denied.
Common policies
-- Users can only access their own files
CREATE POLICY "owner_access" ON storage_objects
FOR ALL USING (auth.uid() = owner_id);
-- Anyone can view files in the public folder
CREATE POLICY "public_read" ON storage_objects
FOR SELECT USING (name LIKE 'public/%');
-- Users can only upload to their own folder
CREATE POLICY "user_folder" ON storage_objects
FOR INSERT USING ((storage.foldername(name))[1] = auth.uid()::text);Policies are defined per-bucket and support:
SELECT- Read/download filesINSERT- Upload new filesUPDATE- Overwrite existing filesDELETE- Remove files
See Storage Policies for complete examples.
Buckets
Buckets organize your files into logical groups. Each bucket can have:
- File size limit - Maximum file size in bytes
- Allowed MIME types - Restrict to specific file types
- Access policies - Control who can read, write, update, and delete files
// Create a bucket via API
const response = await fetch('/storage/buckets', {
method: 'POST',
headers: {
'Authorization': `Bearer ${serviceKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'user-uploads',
file_size_limit: 10 * 1024 * 1024, // 10MB
allowed_mime_types: ['image/jpeg', 'image/png', 'image/gif']
})
});See Buckets for more details. For CLI workflows, see the Volcano CLI docs.
Storage limits
Your plan sets the account-wide storage allowance and maximum object size. See Plans and limits for current values.
Error codes for file size violations:
413- Plan-based storage quota exceeded or plan-based file size limit exceeded400- Bucket-levelfile_size_limitexceeded, MIME type not allowed, or file exceeds the global 10 GB limit
Bandwidth
Upload and download traffic (including public file serving) counts toward your
platform user's billing-cycle bandwidth allowance (aggregate ingress + egress across owned
projects), configured via FREE_BANDWIDTH_CAP / PRO_BANDWIDTH_CAP (in GB;
0 = unlimited). Once the platform user is over the cap, storage requests are
rejected with 429 until the cap increases (plan/override) or the monthly meter
resets.
File visibility
Files are private by default. You can make individual files public:
// Make a file public
await volcano.storage
.from('files')
.updateVisibility('report.pdf', true);
// Get a shareable public URL (no authentication required)
const { data } = volcano.storage
.from('files')
.getPublicUrl('report.pdf');
console.log(data.publicUrl);
// https://api.yourapp.com/public/{projectId}/files/report.pdf
// This URL can be shared anywhere - no SDK needed!Public and private files can coexist in the same bucket. Only the file owner
(or a service key) can change visibility. Configured UPDATE policies also
apply to owner visibility changes.
Authenticated downloads use Cache-Control: private, no-store.
Public downloads can be cached by browsers and shared caches for up to five
minutes. Visibility changes and deletions can therefore take up to five minutes
to propagate to clients that already cached the file.
SDK methods
The JavaScript SDK provides these methods:
| Method | Description |
|---|---|
from(bucket) | Select a bucket for operations |
upload(path, file) | Upload a file (private by default) |
download(path) | Download a file as Blob |
list(prefix) | List files with optional prefix |
remove(paths) | Delete one or more files |
move(from, to) | Move/rename a file |
copy(from, to) | Copy a file |
updateVisibility(path, isPublic) | Make file public or private |
getPublicUrl(path) | Get shareable public URL (no auth needed) |
See JavaScript SDK for the complete reference.
REST API
All storage operations are also available via REST API:
| Method | Endpoint | Description |
|---|---|---|
POST | /storage/{bucket}/{path} | Upload file |
GET | /storage/{bucket}/{path} | Download file |
DELETE | /storage/{bucket}/{path} | Delete file |
GET | /storage/{bucket} | List files |
POST | /storage/{bucket}/move | Move file |
POST | /storage/{bucket}/copy | Copy file |
PATCH | /storage/{bucket}/{path}/visibility | Set public/private |
GET | /public/{projectId}/{bucket}/{path} | Download public file (no auth) |
See Storage API Reference for complete documentation.
What's next
| Guide | Description |
|---|---|
| JavaScript SDK | Complete SDK reference |
| Storage Policies | Access control with RLS-style policies |
| Buckets | Creating and managing buckets |
| API Reference | REST API endpoints |