Database Buckets (dbBuckets)
Store small files directly in the database — icons, avatars, secret documents — without external storage infrastructure.
Database Buckets (dbBuckets)
Database Buckets store files directly in the service's database (BYTEA in PostgreSQL, Buffer in MongoDB) instead of using an external storage service. They are ideal for small files like icons, avatars, secret documents, and configuration files where simplicity and data locality matter more than scalability.
When to Use
| Use Case | Use dbBucket | Use External Bucket Service |
|---|---|---|
| User avatars, icons | Yes | |
| Tenant logos | Yes | |
| Secret/signed documents | Yes | |
| Small config files (<10 MB) | Yes | |
| Product images (many, large) | Yes | |
| User uploads (videos, PDFs) | Yes | |
| Public CDN assets | Yes |
Key differences:
| Feature | Database Bucket | External Bucket Service |
|---|---|---|
| Storage | PostgreSQL BYTEA / MongoDB Buffer | S3, MinIO, or local filesystem |
| Max file size | Configurable (default 10 MB) | Configurable (default 10 MB) |
| Authentication | Regular access token (same as all APIs) | Bucket-specific JWT tokens |
| Infrastructure | None — uses the service's existing database | Requires separate bucket service deployment |
| CDN support | No | Yes (S3 + CloudFront) |
| Scalability | Limited by database size | Highly scalable |
Adding a dbBucket to a Service
Add a dbBuckets entry to any service in your project configuration:
{
"dbBuckets": [
{
"bucketBasics": {
"name": "productImages",
"description": "Product photo storage",
"maxFileSizeMb": 5,
"allowedMimeTypes": "image/png,image/jpeg,image/webp"
},
"bucketAuthorization": {
"readAccess": "public",
"writeAccess": "authenticated",
"enableKeyAccess": true
},
"ownerDataObject": {
"hasOwnerDataObject": true,
"configuration": {
"dataObjectName": "product",
"relationProperty": "productId"
}
}
}
]
}
What Gets Auto-Generated
When you add a dbBucket to a service, the system automatically generates:
1. Data Object: sys_{bucketName}File
A database table with these properties:
| Property | Type | Description |
|---|---|---|
id | ID | Auto-generated unique identifier |
fileName | String | Original file name as uploaded |
mimeType | String | MIME type (e.g., image/png) |
fileSize | Integer | File size in bytes |
fileData | Blob | Binary file content (BYTEA in PostgreSQL, Buffer in MongoDB) |
accessKey | String | 12-character random key for shareable access (unique, indexed) |
userId | ID | ID of the user who uploaded the file (from session) |
metadata | Object | Optional JSON metadata (tags, alt text, etc.) |
createdAt | Date | Upload timestamp |
updatedAt | Date | Last update timestamp |
If an owner data object is configured, an additional relation property is added (e.g., productId as ID with a foreign key to the product table).
2. System Upload/Download Routes
These routes are mounted at /bucket/{bucketName}/ on the service:
Upload
POST /bucket/{bucketName}/upload
Content-Type: multipart/form-data
Authorization: Bearer {accessToken}
| Field | Type | Description |
|---|---|---|
file | File | The file to upload (single file, in the file field) |
metadata | JSON string | Optional metadata object |
{ownerRelationProperty} | string | Optional: ID of the owner record (e.g., productId) |
Response (201):
{
"status": "OK",
"action": "upload",
"bucket": "productImages",
"file": {
"id": "a1b2c3d4-...",
"fileName": "photo.jpg",
"mimeType": "image/jpeg",
"fileSize": 245760,
"accessKey": "x7K9mP2nQ4wR",
"userId": "user-uuid-...",
"productId": "product-uuid-...",
"createdAt": "2026-03-27T10:00:00.000Z"
}
}
Note: The response does not include fileData (the binary content). Only metadata is returned.
Download by ID
GET /bucket/{bucketName}/download/{fileId}
Authorization depends on the bucket's readAccess setting:
-
public: No auth required
-
authenticated: Requires valid access token
-
private: Requires access token, and user must be the file owner or an admin
Returns the binary file with appropriate Content-Type and Content-Disposition headers.
Download by Access Key
GET /bucket/{bucketName}/download/key/{accessKey}
When enableKeyAccess is true, anyone with the 12-character access key can download the file — no authentication required. This is useful for shareable links and <img> tags.
3. Metadata Business APIs
Standard CRUD APIs for querying file metadata (without the binary data):
| API Name | Method | Path | Description |
|---|---|---|---|
get{BucketName}File | GET | /v1/sys_{bucketName}Files/:id | Get file metadata by ID |
list{BucketName}Files | GET | /v1/sys_{bucketName}Files | List files with filtering |
delete{BucketName}File | DELETE | /v1/sys_{bucketName}Files/:id | Delete file (metadata + binary) |
These APIs follow the standard Mindbricks Business API patterns — they support pagination, filtering by mimeType, userId, owner relation property, etc. The fileData (Blob) column is excluded from responses.
Authorization
Read Access (readAccess)
| Value | Behavior |
|---|---|
public | Anyone can download. No authentication needed. |
authenticated | Any authenticated user can download. Requires valid access token. |
private | Only the file owner (userId matches session) and admin roles can download. |
Write Access (writeAccess)
| Value | Behavior |
|---|---|
authenticated | Any authenticated user can upload. |
adminOnly | Only users with admin roles (admin, superAdmin) can upload. |
Role-Based Access
For finer control, configure role arrays:
-
readAbsoluteRoles/writeAbsoluteRoles— Roles that bypass all authorization checks -
readCheckRoles/writeCheckRoles— Roles required for access
Custom Auth Scripts
For complex authorization logic, use MScript expressions:
{
"readAuthScript": "this.session.roleId === 'admin' || this.record.userId === this.session.userId",
"writeAuthScript": "this.session.emailVerified === true"
}
Access Key
When enableKeyAccess is true (default), every uploaded file receives a 12-character random access key. Anyone with this key can download the file via /bucket/{name}/download/key/{accessKey}, regardless of other authorization settings. This enables:
-
Public avatar URLs in
<img>tags (no auth headers needed) -
Shareable file links
-
Email-embedded image URLs
Owner Data Object
Pair a bucket with a data object to create a parent-child relationship:
{
"ownerDataObject": {
"hasOwnerDataObject": true,
"configuration": {
"dataObjectName": "product",
"relationProperty": "productId"
}
}
}
This adds a productId property to the bucket's data object with a foreign key relation. Benefits:
-
Filter by owner:
GET /v1/sys_productImagesFiles?productId={id}lists only that product's images -
Cascading deletes: When the owner record is deleted, associated files are also removed
-
Upload with owner: Pass
productIdin the upload form data to link the file
Auth Service Auto-Generated Buckets
The authentication service automatically includes database buckets for avatars — you don't need to configure these manually:
-
userAvatars— Always present. Public read, authenticated write, images only (png/jpeg/webp/gif), 5 MB max. Paired with theuserdata object. -
{tenantName}Avatars— Only in multi-tenant projects. Same config, paired with the tenant data object.
Avatar Upload Workflow
-
User selects an image
-
Crop with
react-easy-crop(zoom, pan, crop) -
Upload cropped blob:
POST {authBaseUrl}/bucket/userAvatars/upload -
Get back
accessKeyfrom the response -
Build public URL:
{authBaseUrl}/bucket/userAvatars/download/key/{accessKey} -
Save URL to user profile:
updateProfile({ avatar: downloadUrl })
Since readAccess is public, avatar URLs work directly in <img> tags without authentication.
Examples
Simple Icon Bucket (No Owner)
{
"bucketBasics": {
"name": "appIcons",
"description": "Application icon storage",
"maxFileSizeMb": 2,
"allowedMimeTypes": "image/png,image/svg+xml"
},
"bucketAuthorization": {
"readAccess": "public",
"writeAccess": "adminOnly",
"enableKeyAccess": true
}
}
Private Document Bucket (With Owner)
{
"bucketBasics": {
"name": "contracts",
"description": "Signed contract documents — private to owner",
"maxFileSizeMb": 10,
"allowedMimeTypes": "application/pdf"
},
"bucketAuthorization": {
"readAccess": "private",
"writeAccess": "authenticated",
"enableKeyAccess": false
},
"ownerDataObject": {
"hasOwnerDataObject": true,
"configuration": {
"dataObjectName": "employee",
"relationProperty": "employeeId"
}
}
}
Frontend Upload Example
// Upload a file to a dbBucket
async function uploadToBucket(serviceBaseUrl, bucketName, file, accessToken, metadata = {}) {
const formData = new FormData();
formData.append('file', file);
if (Object.keys(metadata).length > 0) {
formData.append('metadata', JSON.stringify(metadata));
}
const response = await fetch(`${serviceBaseUrl}/bucket/${bucketName}/upload`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${accessToken}` },
body: formData,
});
const result = await response.json();
return result.file; // { id, fileName, mimeType, fileSize, accessKey, ... }
}
// Build a public download URL
function getPublicUrl(serviceBaseUrl, bucketName, accessKey) {
return `${serviceBaseUrl}/bucket/${bucketName}/download/key/${accessKey}`;
}
// Usage
const file = await uploadToBucket(authBaseUrl, 'userAvatars', croppedBlob, token);
const avatarUrl = getPublicUrl(authBaseUrl, 'userAvatars', file.accessKey);
await updateProfile({ avatar: avatarUrl });
Last updated today
Built with Documentation.AI