File System
File system architecture and organization in TMA Cloud.
File system architecture and organization in TMA Cloud.
File Structure
Hierarchical Organization
- Root Level: User's root directory
- Folders: Nested folder structure
- Files: Stored within folders or root
File Metadata
- ID: Unique identifier (stable across operations)
- Name: File or folder name
- Type: 'file' or 'folder'
- Size: File size in bytes
- MIME Type: Actual MIME type detected from file content (not from extension)
- Parent ID: Parent folder reference
- Path: The storage key, not a user-visible path
- User ID: The account the item belongs to
- Last Access Time: When the item was last read (
accessed_at), shown in the UI as "Last opened" - Shared At: When the item most recently became shared (
shared_at); null while the item is not shared
File Operations
Supported Operations
- Upload: Add new files
- Download: Retrieve files
- Create Folder: Create new directories
- Move: Move files/folders
- Copy: Duplicate files/folders
- Rename: Change file/folder names
- Delete: Move to trash
- Star: Mark as favorite
- Share: Create share links
Large File Handling
- Streaming: Files streamed without loading into memory
- Upload: Files encrypted and streamed directly to the bucket
- Download: Files streamed from storage to client; single-file downloads support HTTP
Range(partial content) for seeking - ZIP Archives: Archive entries are read through a database cursor and streamed one at a time, keeping database pages and open storage streams bounded
- Rename: Change file/folder names
Performance
- Streaming prevents memory exhaustion for large files (>1GB)
- Rename operations update database metadata without moving stored objects
- Copy operations are queued on the background worker, use server-side object-store copy with four transfers at most, and read folder trees once before batched inserts
- File lists use stable cursor batches and load continuously as the user scrolls. Only visible grid/list rows plus a small overscan are rendered
- Folder sizes and descendant counts are maintained by database triggers. Size sorting uses those stored totals and the matching page-order index instead of walking a folder tree during a listing
- No file size limits imposed by memory constraints
Path Management
- Renaming or moving an item changes its
parent_idandname, not its storage key, so no stored object is touched - Stored object keys are validated as flat keys without path separators or traversal sequences
Last Access Time
Every file and folder carries an accessed_at timestamp, surfaced in the UI as Last opened in Get Info and as a sort option in the file list. It answers "when was this last read", which modified cannot, since modified only moves when the contents change.
What Counts as Reading
| Action | Updates |
|---|---|
| Downloading a file | That file |
| Downloading a folder as ZIP | The folder and everything in it |
| Bulk download | Every item in the archive |
| Opening a document in OnlyOffice | That file |
| Reading a file through a share link | That file |
| Opening a folder in the file list | The folder only, not its contents |
| Uploading or replacing a file | That file |
Listing a folder marks the folder and leaves its children alone. This matches how Windows treats directory enumeration, and it keeps the value meaningful: if browsing past a file counted as opening it, every file in a folder you visit would look recently used.
Searching, viewing Get Info, renaming, moving, starring and sharing do not count as reads.
Write Behavior
Recording a read on every request would turn each read into a database write. Two rules keep that cost bounded, both taken from how filesystems handle the same problem:
- One-hour window. Once an item's timestamp is written, further reads of it are ignored until the window passes. NTFS guarantees its last-access time only to within an hour for the same reason; Linux's
relatimeuses a comparable rule. - Buffered writes. Updates accumulate in memory and are written in one batched statement every 10 seconds, so no read waits on a write. Linux's
lazytimeworks the same way.
The effect is at most one write per item per hour, batched. The number of statements is set by the flush interval rather than by how many users are reading, so it does not grow with traffic. Timestamps may lag by the flush interval plus the window, which is why the value is documented as approximate.
Set ACCESS_TIME_TRACKING=0 to switch the feature off. See Environment Variables for the tuning knobs.
On the Cloud Drive
The mounted Windows drive reports this value as the NTFS LastAccessTime, so Explorer's Date accessed column reflects it. The other three NTFS timestamps come from the modification time. Windows writes LastAccessTime back when a handle closes; the drive accepts and discards those writes, because the server decides what counts as a read. See Desktop App.
Storage
Physical Storage
- S3: Files stored in S3-compatible object storage. Database stores object key.
- Bucket configuration is required before starting the backend.
- Original filenames preserved in database
File Encryption
- Files encrypted with AES-256-GCM in Google Tink's AES-GCM-HKDF-STREAMING format (the
AES256_GCM_HKDF_1MBscheme) - Each newly encrypted object version uses a random data key (DEK).
FILE_ENCRYPTION_KEYis the key-encryption key (KEK) that wraps the DEK; a server-side logical copy reuses the source ciphertext and wrapped DEK - Each object has a 40-byte header (a random salt and nonce prefix) followed by 1 MB segments, each sealed with its own authentication tag. The per-file encryption key is derived from the DEK with HKDF-SHA256
- Segments make stored objects seekable: a download serves an HTTP
Rangerequest by fetching and decrypting only the overlapping segments, so a large file opens without reading all of it - Automatic decryption on download
- Rotate
FILE_ENCRYPTION_KEYwithrotate-kek.js, which only rewraps the stored DEKs and never re-encrypts the objects. See CLI Commands
Storage Limits
- Per-user storage limits
- Configurable by administrators
- Real-time usage tracking
Trash System
Soft Delete
- Files moved to trash (not deleted)
deleted_attimestamp set- Restorable within retention period
Automatic Cleanup
- Trash items deleted after 15 days
- Background worker handles cleanup
- Permanent deletion after retention
- Manual permanent deletion and Empty Trash run on background worker
Search
Trigram Similarity Search
- PostgreSQL pg_trgm extension for fuzzy text matching
- GIN index on file names for fast searches
- Prefix matching for short queries
- Indexed trigram matching for longer queries
- Real-time search results
- User-scoped searches
Related Topics
- Storage Management - Storage limits
- Sharing Model - How files are shared
- User Guide: Upload Files - How to use the file system