Object Storage #26796
dannykopping
started this conversation in
RFCs
Object Storage
#26796
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
RFC: Object Storage
We're exploring how Coder should store large payloads, and we'd love input from operators and self-hosters before we commit to a direction.
What we'd love feedback on (TL;DR):
Details below.
Problem
Since our pivot to AI, we have new use cases that require storing large payloads: LLM transcripts, file uploads, tool results, and similar collateral. We already store some large content (template files, chat files, chat messages) directly in Postgres.
Storing large blobs directly in Postgres works, but it doesn't scale. In our testing, reading large values out of Postgres caused roughly 2-3x memory amplification on the database (the value is fully materialized and then re-encoded onto the wire). As deployments grow, especially with Agents and AI usage, this becomes a real scaling problem.
Evidence
Postgres stores oversized values using TOAST, transparently compressing and chunking them. On read, these values must be fully materialized in the backend and then encoded onto the wire (usually hex), which allocates additional memory. We measured resident-memory amplification while reading 10-50 MiB payloads:
Full benchmark and methodology: https://gist.github.com/dannykopping/574c952c8cd1664640d73298367c4d7b
Proposal
Introduce an Object Storage service with pluggable backends:
Objects are tracked in the database regardless of backend. With the Postgres backend, contents live in the database; with an external backend, only a reference is stored.
The service exposes a small, streaming Go interface so reads and writes don't have to buffer entire objects in memory:
It's built on the Go CDK
bloblibrary, which provides integration with S3, GCS, and Azure Blob (plus any S3-compatible service for air-gapped installs).Configuration
The configuration surface is intentionally minimal: pick a backend and point it at a bucket.
Credentials come from the standard auth chains for each provider (environment, instance metadata, profiles). Coder will surface a clear, actionable error on startup if the selected backend can't be initialized or authenticated.
Guarantees
From a user's perspective, all backends provide:
Switching backends
Operators can change backends without a maintenance window. Each object records which backend stored it, so old and new backends coexist: existing objects keep resolving from their original backend while new writes go to the new one, and old records age out over time. A hard cutover (migrating all existing objects at once) is out of scope for now.
What this gives operators
Future possibilities
Not in the initial scope, but likely candidates later, and we'd value opinions on prioritization:
Where large payloads come from today
files): compressed user-uploaded template files and provisioner-generated Terraform module caches, used for provisioning.chat_messages): raw payloads of LLM interactions for Coder Agents users.chat_files): files uploaded by Coder Agents users and generated by agents (screenshots, recordings). User uploads are capped at 10 MiB; agent-generated files are unbounded.Looking ahead, AI Gateway may need to store full LLM inference transcripts (requests and responses), similar in shape to what
chat_messagesstores today.Alternatives considered
Postgres Large Objects API. Postgres has a Large Objects API that predates
byteaand superficially offers streaming access. We discarded it because it isn't supported by our Postgres driver (open >12 years), its read API is just successive server round-trips rather than true streaming, and orphan cleanup is a separate operational burden (vacuumlo).Do nothing. We could keep storing everything in Postgres, but customers rolling out Agents to any non-trivial number of users will hit serious scaling problems.
Questions for the community
Beta Was this translation helpful? Give feedback.
All reactions