Announcing the Tigris Storage SDK

A blue tiger with a laptop under his shoulder walks to work, greeting a floating robotic datacentre technician on his way to his office.
At Tigris, we do object storage. However, in order to use Tigris in your JavaScript or TypeScript projects, you normally have to import a library from AWS. We want you to import Tigris to use Tigris, so we made the Tigris Storage SDK to make interactions with object storage simpler. Here’s how you use it compared to the AWS S3 SDK:
Tigris Storage SDK
import { put } from "@tigrisdata/storage";
await put("object.txt", "Hello, World!");
You can get started with the Tigris Storage SDK by installing the NPM package
@tigrisdata/storage
:
- npm
- Yarn
npm install --save @tigrisdata/storage
yarn add @tigrisdata/storage
From there, create a bucket,
create an Editor keypair for that bucket,
and add the following to your .env
file (or to the project’s environment in
your runtime of choice):
TIGRIS_STORAGE_ACCESS_KEY_ID=tid_access_key_id
TIGRIS_STORAGE_SECRET_ACCESS_KEY=tsec_secret_access_key
TIGRIS_STORAGE_BUCKET=mybucket
That’s it!
Why make a storage SDK?
Object storage is a very simple concept that ended up being complicated in
practice. When we designed the Tigris Storage SDK, we wanted to pare it down to
the bare essentials. If you need to put an object into Tigris, you use the put
function. This automatically figures out where to store things, what credentials
to use, and all the other minutæ you have to deal with. You just put, get, list,
and delete objects.
This adds up to give you the ability to glance at the code and have a good idea of what is actually going on. Compare these two code snippets:
Tigris Storage SDK
import { list } from "@tigrisdata/storage";
const { data, error } =
await list({ limit: 100 });
if (error !== undefined) {
console.error("Error listing files:", error);
}
data.forEach(({ name, size }) => {
console.log(`${name}: ${size} bytes`);
});
Which one would you rather read in your codebase? The cognitive complexity reduction in the Tigris Storage SDK is subtle but significant. By default, the Tigris Storage SDK loads all of its configuration from the environment like any good twelve-factor app should:
Tigris Storage SDK | AWS |
---|---|
TIGRIS_STORAGE_ACCESS_KEY_ID | AWS_ACCESS_KEY_ID |
TIGRIS_STORAGE_SECRET_ACCESS_KEY | AWS_SECRET_ACCESS_KEY |
TIGRIS_STORAGE_BUCKET | No equivalent, you must set it manually per call |
AWS_ACCESS_KEY_ID
➡️TIGRIS_STORAGE_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
➡️TIGRIS_STORAGE_SECRET_ACCESS_KEY
TIGRIS_STORAGE_BUCKET
➡️ No equivalent, you must set it manually per call
However, if you need to put
things into a different bucket, you can do that
with the config
argument:
import { put } from "@tigrisdata/storage";
const { data, error } = put(`avatars/${user.id}`, avatarBlob, {
addRandomSuffix: true,
config: {
bucket: "contoso-user-data",
},
});
if (error !== undefined) {
throw error; // or whatever else you do in your project
}
console.log(`Data uploaded to tigris as ${data.path}`);
console.log(`URL: ${data.url}`);
This will put a user’s avatar data into the Tigris bucket contoso-user-data
and suffix the name with the time (in Unix milliseconds) and random data. You
can also
set the access key id, secret access key, and API endpoint on a per-bucket basis.
You may have noticed something interesting in that last example:
const { data, error } = put(`avatars/${user.id}`, avatarBlob);
if (error !== undefined) {
throw error; // or whatever else you do in your project
}
// use data
When possible, we return errors as values instead of throwing exceptions up the stack. This pattern allows you to handle errors inline to your code so they aren’t surprises when they come up in practice. This adds up to reduce the cognitive complexity of your code so you can go back to shipping your multicloud agentic SaaS of your dreams!
This also means you don’t have to instantiate classes or ferry around a client global when you want to do basic operations:
Tigris Storage SDK
import { get } from "@tigrisdata/storage";
const { data, error } = get("object.txt", "string");
if (error !== undefined) {
// or whatever else you do in your project
throw error;
}
console.log(data);
Need to upload a large file? The multipart upload feature is there for you!
const videoStream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode("Hello, World!"));
controller.close();
},
});
const { data, error } = await put("videos/large-video.mp4", videoStream, {
multipart: true,
onUploadProgress: ({ percentage }) => {
console.log(`Upload progress: ${percentage}%`);
},
});
if (error !== undefined) {
throw error; // or whatever else you do in your project
}
console.log(data);
Client uploads
Tigris
does not charge egress fees,
but the provider you run your app on likely does. This means that uploading data
to Tigris from your app can run up a cost per gigabyte. To work around this,
we’ve created the
client upload pattern.
This makes your app return a
presigned PUT
URL to the
client and then the client uploads the data directly to Tigris, sidestepping the
entire part where your app needs to stream data from the client and then upload
it to Tigris.
In order to implement this, you need to do the following:
- Expose an upload endpoint that creates pre-signed URLs, for example:
/api/upload
- Call the
upload
function from@tigrisdata/storage/client
module like this:
import { upload } from "@tigrisdata/storage/client";
const { data, error } = await upload(file.name), file, {
url: "/api/upload", // or whatever endpoint you use
access: "private", // or public
onUploadProgress: ({ loaded, total, percentage }) => {
console.log({ loaded, total, percentage });
},
};
if (error !== undefined) {
throw error; // or whatever you do normally
}
console.log(data);
And then your data is uploaded by the client instead of having to pipe it through to the server! Make sure to secure this API endpoint appropriately, add rate limits, and all the other protections you should do for production services. Note that you may need to combine this with setting CORS for your bucket and using custom branded presigned URLs for the best effect.
Conclusion
If you want to try the Tigris Storage SDK, install it from npm:
- npm
- Yarn
npm install --save @tigrisdata/storage
yarn add @tigrisdata/storage
If you want to learn more about the Tigris Storage SDK, check out these links for more information:
Globally performant object storage
Tigris is dedicated to making sure that your experience with object storage is the best it can possibly be, and then we go the extra mile to make it even better.