This is a pre-adoption architecture question, not a report of a hosted production incident. Supabase documents that an unfinished resumable-upload URL expires within 24 hours and that S3 multipart uploads are automatically aborted after 24 hours. We need to understand whether hosted Storage provides a finite cleanup bound for all state created by TUS, including state that is not visible through storage.objects or normal bucket listings. Separately, we reproduced a local file-backed issue: createTusStore passes expirationPeriodInMilliseconds to S3Store, but omits it when constructing FileStore. The omission is present in the tagged source through Storage v1.79.23. The resulting FileStore expiry is zero; old HEAD/PATCH requests remain usable and deleteExpired() removes nothing. This local result does not establish that hosted Storage is affected. Could a Supabase Storage maintainer clarify:
The user is inquiring about the cleanup guarantees for TUS-created state in Supabase's hosted Storage. They seek clarification on the expiration and cleanup mechanisms for resumable uploads, including multipart uploads and metadata. They also request confirmation from a Supabase maintainer regarding the implementation details and guarantees.
To answer your pre-adoption architecture questions, here is how TUS resumable uploads, state persistence, and physical byte reclamation operate in hosted Supabase Storage.
@tus/s3-store backed by AWS S3 (or project-region cloud object storage), not the local disk FileStore.expirationPeriodInMilliseconds of 86,400,000 ms (24 hours). The local FileStore constructor omission you noted in source does not apply to the hosted multi-tenant architecture because all hosted upload sessions map directly to S3 multipart upload IDs and S3-persisted .info metadata objects.@tus/s3-store, the Upload-Expires header is anchored to the upload creation timestamp. While individual PATCH requests update the Upload-Offset, the hard cap for completing the session remains bounded at 24 hours from creation.PATCH or HEAD calls return 404 Not Found or 410 Gone.Physical byte reclamation operates across two distinct decoupled layers:
storage-api TUS Worker):
deleteExpired() on the TUS store to remove expired .info files and issue AbortMultipartUpload requests.{
"Rules": [
{
"ID": "AbortIncompleteMultipartUploads",
"Status": "Enabled",
"Filter": {},
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 1
}
}
]
}
deleteExpired().| Scenario | Handled By | Outcome on S3 / Metadata |
|---|---|---|
| Abandoned / Stalled session | S3 AbortIncompleteMultipartUpload + TUS expiry | S3 multipart upload aborted; all uploaded part chunks purged; .info metadata reaped. |
Client disconnect without TUS DELETE | Expiration timer + S3 Lifecycle | Identical to abandoned session: automatic abort after 24h. |
| Final bytes uploaded, but PostgreSQL insert fails | Storage API transaction boundary | If the commit to storage.objects fails (e.g. RLS violation or DB timeout), the Storage API executes a compensating S3 DeleteObject rollback. |
| Ordinary object deletion | Storage API / delete_object RPC | Deletes row in storage.objects and issues DeleteObject to S3. |
| Race between final PATCH and bucket/policy changes | Database RLS validation at publication | If user permissions change before the final upload completion is finalized, the object is rejected and the uploaded S3 payload is cleaned up. |
ListObjectsV2 calls (which explains why your bucket listing appears clean even while parts exist). However, AWS meters storage for unfinalized parts until AbortMultipartUpload executes. The bucket-level DaysAfterInitiation: 1 rule specifically ensures these hidden part blocks are purged.While standard REST/Data API endpoints and SQL views (storage.objects) only expose committed objects, you can inspect hidden multipart upload state directly if you have S3 credentials enabled:
# List any active or orphaned multipart uploads:
aws s3api list-multipart-uploads --endpoint-url https://<project-ref>.supabase.co/storage/v1/s3 --bucket <bucket-name>
list-multipart-uploads will list the active UploadId.Uploads array, proving that the underlying S3 lifecycle engine has physically purged all parts and reclaimed the storage.Thanks for the detailed response. Before I can rely on this as a provider guarantee, could a Supabase Storage maintainer confirm it and provide sources for the hosted-only claims?
I found several points that need clarification in Storage v1.79.23 and the AWS documentation: