On this page

What you get

Per project: an S3-compatible bucket, accessed through MIOSA endpoints. Credentials injected as env vars:


STORAGE_BUCKET=miosa-proj_xxx-uploads
STORAGE_ENDPOINT=https://storage.miosa.app
STORAGE_KEY_ID=...
STORAGE_KEY_SECRET=...

Your code uses the standard S3 client libraries:

import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"

const s3 = new S3Client({
  endpoint: process.env.STORAGE_ENDPOINT,
  credentials: {
    accessKeyId: process.env.STORAGE_KEY_ID!,
    secretAccessKey: process.env.STORAGE_KEY_SECRET!,
  },
  region: "us-east-1",
})

await s3.send(new PutObjectCommand({
  Bucket: process.env.STORAGE_BUCKET,
  Key: "uploads/foo.png",
  Body: pngBuffer,
}))

Signed URLs for browser uploads

Don’t proxy file uploads through your runtime. Mint a signed URL server-side; the browser uploads directly to storage:

// Server
const url = await miosa.storage.signedUrl({
  bucket: process.env.STORAGE_BUCKET!,
  key: `users/${userId}/avatar.png`,
  operation: "put",
  expiresInSec: 300,
  contentType: "image/png",
})
return { uploadUrl: url }
// Browser
await fetch(uploadUrl, {
  method: "PUT",
  body: file,
  headers: { "Content-Type": "image/png" },
})

Same pattern for downloads (operation: "get"). Signed URLs are scoped (single key, single operation, short expiry) — no risk of leaking bucket-wide credentials to a browser.

Public vs private

Each object can be private (default; access only via signed URL) or public (served from a *.storage.miosa.app URL). Public objects can also be fronted by a custom domain via your project’s Domain settings.

Bandwidth and storage costs

Two billable dimensions:

  • Storage — GB-month for stored bytes.
  • Egress — GB out from MIOSA to the public internet. Storage-to-runtime within MIOSA is free.

Attribution is carried on every event for chargeback.

Limits

LimitDefaultTunable
Storage per project1 GBYes (plan-dependent)
Max object size5 GBUp to 100 GB for multipart
List keys per call1000Standard S3 pagination

Sandboxes can use the bucket too

The same env vars are injected into sandboxes for dev / testing. Upload from inside a sandbox:

await sandbox.exec({
  cmd: "aws",
  args: ["s3", "cp", "/workspace/build.tar.gz", `s3://${process.env.STORAGE_BUCKET}/builds/`],
  env: {
    AWS_ACCESS_KEY_ID: process.env.STORAGE_KEY_ID,
    AWS_SECRET_ACCESS_KEY: process.env.STORAGE_KEY_SECRET,
    AWS_ENDPOINT_URL: process.env.STORAGE_ENDPOINT,
  },
})

Bring your own bucket?

Yes. Set the env vars to point at an external S3-compatible bucket (real AWS, Backblaze B2, R2, etc.). MIOSA injects whatever you set.

Python SDK

See also

Was this helpful?