1---
2title: Tigris
3description: S3-compatible object storage billed through Fly. Bind Fly.PutObject / Fly.GetObject.
4---
5
6A [`Fly.Bucket`](/providers/fly/bucket) is Tigris S3-compatible
7object storage, billed through Fly. It is org-scoped. There is no
8parent [App](/fly/compute/apps).
9
10Tigris speaks the S3 API. Bind [`PutObject`](/providers/fly/putobject)
11/ [`GetObject`](/providers/fly/getobject) in a
12[Service](/fly/compute/services). Alchemy injects the Tigris
13endpoint and credentials. You never read `AWS_*` yourself.
14
15## Create a Bucket
16
17Alchemy generates a unique name unless you pass one.
18
19```typescript
20const data = yield* Fly.Bucket("Data");
21```
22
23## A stable name
24
25Pass `name` when you need a stable Tigris bucket name.
26
27```typescript
28const data = yield* Fly.Bucket("Data", {
29 name: "my-bucket",
30});
31```
32
33:::caution[Changing `name` replaces the Bucket]
34Tigris cannot rename a bucket. Alchemy creates the new name, then
35deletes the old one.
36:::
37
38## Put and get objects
39
40Bind `PutObject` / `GetObject` in the Service's constructor. Provide the matching
41`*Http` layers.
42
43```typescript
44import * as HttpServerResponse from "effect/http/HttpServerResponse";
45
46export default class Api extends Fly.Service<Api>()(
47 "Api",
48 { main: import.meta.url, port: 3000 },
49 Effect.gen(function* () {
50 const putObject = yield* Fly.PutObject(Data);
51 const getObject = yield* Fly.GetObject(Data);
52
53 return {
54 fetch: Effect.gen(function* () {
55 yield* putObject({
56 Key: "hello.txt",
57 Body: "hello",
58 ContentType: "text/plain",
59 });
60 const obj = yield* getObject({ Key: "hello.txt" });
61 return HttpServerResponse.json({ ok: obj.ETag !== undefined });
62 }),
63 };
64 }).pipe(Effect.provide([Fly.PutObjectHttp, Fly.GetObjectHttp])),
65) {}
66```
67
68## Public access
69
70Buckets are private by default. `public: true` serves objects
71without credentials.
72
73```typescript
74const assets = yield* Fly.Bucket("Assets", {
75 public: true,
76});
77```
78
79## Custom domain
80
81`domainName` sets `website.domain_name` on the add-on. Point a
82CNAME at `{name}.t3.tigrisbucket.io`.
83
84```typescript
85const assets = yield* Fly.Bucket("Assets", {
86 public: true,
87 domainName: "assets.example.com",
88});
89```
90
91## Organization
92
93Org defaults to the current token. Pass `orgSlug` to pin it.
94
95```typescript
96const data = yield* Fly.Bucket("Data", {
97 orgSlug: "my-org",
98});
99```
100
101:::caution[Changing `orgSlug` replaces the Bucket]
102The bucket is created in the new org. The old bucket is deleted.
103:::
104
105## Where next
106
107[Services](/fly/compute/services) is the Machine that binds
108`PutObject` / `GetObject`.
109The [`Bucket` reference](/providers/fly/bucket) lists every prop.