Railway Buckets

Upload files directly from the browser to Railway Buckets with presigned URLs, while Convex stores and reactively queries all file metadata.

Installation

npm install convex-railway-buckets

About Railway Buckets

Railway Buckets is a Convex component that integrates Railway's S3-compatible object storage with your Convex backend. Browsers upload files directly to the bucket via presigned PUT URLs signed with a built-in SigV4 implementation, while Convex stores and queries file metadata reactively. Upload policies, access checks, and post-upload hooks all run inside Convex transactions, keeping your file records consistent with the rest of your data.

Benefits

Use cases

how to upload files to Railway Buckets from a Convex app

The convex-railway-buckets component provides a useUploadFile React hook and a generateUploadUrl mutation that signs a presigned PUT URL. The browser uploads directly to the bucket, then calls verifyUpload and completeUpload to record metadata in Convex. No file bytes pass through Convex functions.

how to store file metadata in Convex when uploading to S3-compatible storage

convex-railway-buckets records file metadata in a Convex table managed by the component and exposes reactive getFile and listFiles queries. The onUpload callback lets you insert rows into your own tables in the same transaction, keeping your data consistent with the stored file.

how to serve private files from Railway Buckets with expiring URLs

Railway Buckets are always private. The component's getFile and listFiles functions return presigned GET URLs valid for one hour by default, configurable up to 7 days. For stable image src attributes that never expire, registerRoutes adds an HTTP endpoint that issues a fresh presigned redirect on every request.

how to upload files to object storage from a Convex action server-side

The convex-railway-buckets component exposes a buckets.store(ctx, body, options) method callable from any Convex action. It accepts a Blob, ArrayBuffer, Uint8Array, or string, skips the upload policy since server code is trusted, and refuses to overwrite an existing key by throwing KEY_IN_USE.

Frequently asked questions

Does convex-railway-buckets require the AWS SDK?

No. convex-railway-buckets includes a minimal SigV4 signer built on Web Crypto. It runs in Convex queries, mutations, actions, and HTTP actions without any AWS SDK dependency.

How does convex-railway-buckets prevent unauthorized uploads?

Each presigned upload URL is signed for one exact file size and content type, and only succeeds if no object exists at the key yet. The URL also embeds a random upload ID in x-amz-meta-upload-id. Only the identity that requested the URL can call verifyUpload and completeUpload, and each step verifies the caller matches the original requester.

What happens if a browser upload is abandoned before completion?

convex-railway-buckets tracks pending uploads and, after the URL lifetime plus a completeWithin window (6 hours by default), automatically deletes any partially uploaded object and removes the pending record. The delete targets only the object carrying the specific upload ID, so it cannot affect unrelated objects at the same key.

Can convex-railway-buckets be used outside of React?

Yes. The convex-railway-buckets/browser export provides an uploadFile function that accepts a ConvexClient, ConvexReactClient, or ConvexHttpClient, with no React dependency. This makes it usable with Svelte, Vue, or plain JavaScript.

What version of Convex does convex-railway-buckets require?

convex-railway-buckets requires convex 1.39 or newer. This minimum version is required for component environment variable support, which is how Railway Bucket credentials are securely bound to the component without appearing in function arguments, scheduled jobs, or database tables.

Links