Files and media
Use the Files SDK or Media SDK to save files that need to survive app restarts and redeployments. For an overview, see Keelson SDK.
Use Files for files your app reads and writes internally, and Media for files displayed in the app or opened by users. Media provides URLs that browsers can open directly, making it suitable for images and attachments.
Choose by use case
Section titled “Choose by use case”| Files SDK | Media SDK | |
|---|---|---|
| Main use | Save and update files used in internal app processing | Display images and let users open PDFs or attachments |
| Examples | Configuration JSON, lists of processed URLs, intermediate summary files | Product photos, application PDFs, user-facing reports |
| Reading | Server-side code reads through the SDK. No serving URL is provided | Server-side code can read files, and browsers can open them by URL |
| Updates | Overwrite the same name (key). Aim for roughly one update per key per second | Each newly saved file gets an ID; existing files cannot be overwritten |
| Maximum file size | 10 MiB | 50 MiB |
Choose based on how a file is used, not just its format. A CSV used internally for calculations fits Files; a CSV report delivered to users fits Media.
Media URLs are not public links that anyone can open. Only members who can view the app can open them after signing in to Keelson. Neither Files nor Media requires additional keelson.yaml configuration.
Media access is controlled at the app level. It does not automatically enforce per-file permissions, such as allowing users to see only their own attachments. For those cases, consider storing files in Files and having the app check permissions before returning them.
Keep files after a restart
Section titled “Keep files after a restart”Data written to local files while the app runs does not survive restarts or redeployments. Writing to /tmp or the app directory alone does not preserve files for later use.
Once a Files / Media SDK save completes, the file survives app restarts. No later synchronization step is needed. Use Managed SQLite for customer records, projects, and other data you search and update by field.
Installation
Section titled “Installation”Follow Keelson SDK installation to add Files or Media to your app’s dependencies. The examples below run on the server. You can usually ask your AI agent to implement storage by explaining what files you want to save and how they will be used.
Files SDK
Section titled “Files SDK”Files works well for files that your app saves under a name and updates under that same name. Saved files can be shared between the web app and its scheduled jobs.
The storage name is called a “key,” such as settings.json or reports/2026-08.csv. The main Node.js / Python operations are write to save, read to read, delete to remove, and list to list keys. If a file does not exist, read returns null in Node.js or None in Python.
This example saves and reads settings, lists reports, and deletes an old report.
import * as files from "@keelsonhq/files";
await files.write("settings.json", JSON.stringify({ theme: "dark" }));const raw = await files.read("settings.json"); // Uint8Array | nullconst settings = raw ? JSON.parse(new TextDecoder().decode(raw)) : {};const keys = await files.list("reports/"); // ["reports/2026-08.csv", ...]await files.delete("reports/2026-07.csv");import jsonfrom keelson import files
files.write("settings.json", json.dumps({"theme": "dark"}))settings = json.loads(files.read("settings.json") or "{}") # read() -> bytes | Nonekeys = files.list("reports/")files.delete("reports/2026-07.csv")When moving from local files, change both reads and writes to use the SDK. Files does not provide serving URLs. To deliver a saved file to users, implement a download handler in your app or use Media.
If multiple processes read and update the same key, one update may overwrite another. Use database transactions for processing status, counters, or other data that needs concurrent updates.
Media SDK
Section titled “Media SDK”Media is suitable for images displayed in the app and PDFs or attachments users open. Keelson serves saved files through URLs, so your app does not need its own file-serving handler.
Save a file and display it
Section titled “Save a file and display it”- Call
putin server-side code to save the file. - Store the returned file ID in the database alongside the relevant project, product, or other record.
- Get the URL with
url(id)and use it in an image or link. When the browser opens the URL, Keelson checks authentication and returns the file.
The following server-side function saves an image. Pass the uploaded image bytes as its argument.
import * as media from "@keelsonhq/media";
async function savePhoto(imageBytes) { const id = await media.put(imageBytes, { contentType: "image/png", filename: "photo.png", }); // Store id in the database and return url to the frontend. return { id, url: media.url(id) };}from keelson import media
def save_photo(image_bytes): file_id = media.put( image_bytes, content_type="image/png", filename="photo.png", ) # Store file_id in the database and return url to the frontend. return {"id": file_id, "url": media.url(file_id)}On Keelson, URLs have the form /__keelson/media/<file-id>. For example, set an image’s URL as an <img> element’s src, or a PDF’s URL as a link’s href.
<!-- Example URLs for saved files --><img src="/__keelson/media/image-file-id" alt="Product photo" /><a href="/__keelson/media/pdf-file-id">Open application form</a>Keelson handles the file read. Knowing the URL is not enough to open it; the user needs permission to view the app.
Updates, deletion, and other operations
Section titled “Updates, deletion, and other operations”Saved files cannot be overwritten. To replace a file, save a new one and update the ID in the database. Delete the old file separately when it is no longer needed.
- Use
get(id)to read contents on the server, andstat(id)to check the Content-Type and size. - Use
exists(id)to check existence. Delete withdel(id)in Node.js ordelete(id)in Python. - If you omit Content-Type, it is inferred from the filename extension. If it cannot be inferred, it defaults to
application/octet-stream.
Local development
Section titled “Local development”Without Keelson connection settings, both SDKs save files in local folders. These local files are not automatically transferred to Keelson Files / Media when you deploy.
- Files writes actual files under
./.keelson/files/. Add.keelson/to.gitignore. - Media writes under
./media/(configurable withMEDIA_DIR).
On Keelson, the platform sets the required environment variables.
In Media local mode, the default URL is /media/<file-id>. To preview files in a browser, add a handler to your development server that serves them. media.url() returns a URL; it does not start a local HTTP server.
The Files and Media SDKs support local mode on Linux, macOS, and Windows for Node.js, Python, and Go.
The Files SDK maps keys directly to local paths. On Windows and macOS filesystems configured as case-insensitive, keys that differ only by case, such as Report and report, cannot coexist. Path-based backends also have a race if another process replaces a checked component with a symlink or junction before the operation completes. Use them for trusted, single-user local development. The production GCS path does not have this limitation.
File management and capacity
Section titled “File management and capacity”- The console and CLI do not provide file listing, downloading, or replacement for app files. Build a file list in your app for users. For Media, create links from saved IDs; for Files, implement a download handler when needed.
- Store files that exceed the size limits directly in external object storage, such as S3-compatible storage. Outbound connections are unrestricted, except for the SMTP ports.
Files / Media files count toward workspace storage capacity (Plans and limits).
Managed SQLite backups do not include Files / Media file contents. Restoring a database does not restore deleted files.
Related pages
Section titled “Related pages”- Database (Managed SQLite)
- Scheduled jobs — Use the Files SDK from scheduled jobs