A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://docs.netlify.com/build/data-and-storage/netlify-blobs/ below:

Netlify Blobs | Netlify Docs

With Netlify Blobs, you can store and retrieve blobs and unstructured data. You can also use this feature as a simple key/value store or basic database.

Netlify Blobs is a highly-available data store optimized for frequent reads and infrequent writes.

For maximum flexibility, it offers a configurable consistency model. If multiple write calls to the same key are issued, the last write wins.

We automatically handle provisioning, configuration, and access control for you. This integrated zero-configuration solution helps you focus on building business value in your project rather than toil on setting up and scaling a separate blob storage solution.

Each blob belongs to a single site. A site can have multiple namespaces for blobs. We call these stores. This allows you to, for example, have the key my-key exist as an object in a store for file-uploads and separately as an object in a store for json-uploads with different data. Every blob must be associated with a store, even if a site is not using multiple namespaces.

You can perform CRUD operations for Netlify Blobs from the following Netlify features:

You can also:

Netlify Blobs is a platform primitive that developers and frameworks can use as a building block for many different purposes. Here are a few examples of powerful patterns that you can use:

For more advanced use cases — such as those that require complex queries, concurrency control, or a relational data model — explore our integrations with the best-in-class database vendors.

To use the Netlify Blobs API, first install the @netlify/blobs module using the package manager of your choice:

npm install @netlify/blobs

Then use the below methods in your functions, edge functions, or build plugins.

Opens a site-wide store for reading and writing blobs. Data added to that store will be persisted on new deploys, available on all deploy contexts and accessible from from Functions, Edge Functions and Build Plugins.

const store = getStore(name, { siteID, token })

SiteID same as Project ID

Your SiteID appears as the Project ID in the Netlify app UI at app.netlify.com. To find this ID in the Netlify UI, go to Project configuration > General > Project information, and copy the value for Project ID.

SiteID same as Project ID

Your SiteID appears as the Project ID in the Netlify app UI at app.netlify.com. To find this ID in the Netlify UI, go to Project configuration > General > Project information, and copy the value for Project ID.

Find your Netlify site ID

To find your Netlify site ID (also called Project ID in the Netlify UI), go to Project configuration > General > Project information, and copy the value for Project ID

An instance of a store on which you can get, set or delete blobs.

Opens a deploy-specific store for reading and writing blobs. Data added to that store will be scoped to a specific deploy, available on all deploy contexts and accessible from from Functions, Edge Functions and Build Plugins.

const store = getDeployStore(name, { deployID, region, siteID, token })

SiteID same as Project ID

Your SiteID appears as the Project ID in the Netlify app UI at app.netlify.com. To find this ID in the Netlify UI, go to Project configuration > General > Project information, and copy the value for Project ID.

SiteID same as Project ID

Your SiteID appears as the Project ID in the Netlify app UI at app.netlify.com. To find this ID in the Netlify UI, go to Project configuration > General > Project information, and copy the value for Project ID.

An instance of a store on which you can get, set or delete blobs.

Creates an object with the given key and value. If an entry with the given key already exists, its value is overwritten.

await store.set(key, value, { metadata, onlyIfMatch, onlyIfNew })

A Promise that resolves with an object containing the following properties:

This example shows how you might use Netlify Blobs to persist user-generated uploads. For a more in-depth explanation, refer to this guide.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Accessing the request as `multipart/form-data`.

const form = await req.formData();

const file = form.get("file") as File;

// Generating a unique key for the entry.

const key = uuid();

const uploads = getStore("file-uploads");

await uploads.set(key, file, {

metadata: { country: context.geo.country.name }

});

return new Response("Submission saved");

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Accessing the request as `multipart/form-data`.

const form = await req.formData();

const file = form.get("file") as File;

// Generating a unique key for the entry.

const key = uuid();

const uploads = getStore("file-uploads");

await uploads.set(key, file, {

metadata: { country: context.geo.country.name }

});

return new Response("Submission saved");

};

import { readFile } from "node:fs/promises";

import { getDeployStore } from "@netlify/blobs";

import { v4 as uuid } from "uuid";

export const onPostBuild = async () => {

// Reading a file from disk at build time.

const file = await readFile("some-file.txt", "utf8");

// Generating a unique key for the entry.

const key = uuid();

const uploads = getStore("file-uploads");

await uploads.set(key, file, {

metadata: { country: "Spain" }

});

};

The example below shows how you can use the onlyIfMatch and onlyIfNew properties to do atomic, conditional writes.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

export default async (req: Request, context: Context) => {

const emails = getStore("emails");

const { modified } = await emails.set(

"jane@netlify.com",

"Jane Doe",

{ onlyIfNew: true }

);

if (modified) {

return new Response("Submission saved");

}

return new Response("Email already exists", { status: 400 });

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

export default async (req: Request, context: Context) => {

const emails = getStore("emails");

// `myLocalCache` is a stub for a local cache implementation you

// might implement.

const { data, etag } = myLocalCache.get("jane@netlify.com")

const updatedData = {

...data,

lastSeen: Date.now()

}

// Update Jane's information only if it hasn't changed since we

// cached it.

const { modified } = await emails.set(

"jane@netlify.com",

"New Jane",

{ onlyIfMatch: etag }

);

if (!modified) {

return new Response(

"Cached data is stale. Someone else must've updated the data!",

{ status: 400 }

);

}

return new Response("Submission saved");

};

Convenience method for creating a JSON-serialized object. If an entry with the given key already exists, its value is overwritten.

setJSON(key, value, { metadata, onlyIfMatch, onlyIfNew })

A Promise that resolves with an object containing the following properties:

This example shows how you might use Netlify Blobs to persist user-generated data.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Expecting the request body to contain JSON.

const data = await req.json();

// Generating a unique key for the entry.

const key = uuid();

const uploads = getStore("json-uploads");

await uploads.setJSON(key, data, {

metadata: { country: context.geo.country.name }

});

return new Response("Submission saved");

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Expecting the request body to contain JSON.

const data = await req.json();

// Generating a unique key for the entry.

const key = uuid();

const uploads = getStore("json-uploads");

await uploads.setJSON(key, data, {

metadata: { country: context.geo.country.name }

});

return new Response("Submission saved");

};

import { readFile } from "node:fs/promises";

import { getDeployStore } from "@netlify/blobs";

import { v4 as uuid } from "uuid";

export const onPostBuild = async () => {

// Reading a file from disk at build time.

const file = await readFile("some-file.txt", "utf8");

// Expecting the file to contain JSON.

const data = JSON.parse(file);

// Generating a unique key for the entry.

const key = uuid();

const uploads = getStore("json-uploads");

await uploads.setJSON(key, data, {

metadata: { country: "Spain" }

});

};

Retrieves an object with the given key.

await store.get(key, { consistency, type })

A Promise that resolves with the blob in the format specified by type: ArrayBuffer, Blob, Object, ReadableStream or a string.

If an object with the given key is not found, a Promise that resolves with null is returned.

This example shows how you might read user-generated data that has been previously uploaded to Netlify Blobs.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

export default async (req: Request, context: Context) => {

// Extract key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

const entry = await uploads.get(key);

if (entry === null) {

return new Response(`Could not find entry with key ${key}`, {

status: 404

});

}

return new Response(entry);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions";

export default async (req: Request, context: Context) => {

// Extract key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

const entry = await uploads.get(key);

if (entry === null) {

return new Response(`Could not find entry with key ${key}`, {

status: 404

});

}

return new Response(entry);

};

import { getDeployStore } from "@netlify/blobs";

export const onPostBuild = async () => {

const uploads = getDeployStore("file-uploads");

const entry = await uploads.get("my-key");

if (entry === null) {

console.log("Could not find entry");

} else {

console.log(entry);

}

};

Retrieves an object along with its metadata.

This method is useful to check if a blob exists without actually retrieving it and having to download a potentially large blob over the network.

await store.getWithMetadata(key, { consistency, etag, type })

A Promise that resolves with an object containing the following properties:

If an object with the given key is not found, a Promise that resolves with null is returned.

This example shows how you might read metadata from user-generated submissions that have been previously uploaded to Netlify Blobs.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

export default async (req: Request, context: Context) => {

// Extract key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

const { data, metadata } = await uploads.getWithMetadata(key);

if (entry === null) {

return new Response(`Could not find entry with key ${key}`, {

status: 404

});

}

return new Response(entry, { headers: { "X-Country": metadata.country } });

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

// Extract key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

const { data, metadata } = await uploads.getWithMetadata(key);

if (entry === null) {

return new Response(`Could not find entry with key ${key}`, {

status: 404

});

}

return new Response(entry, { headers: { "X-Country": metadata.country } });

};

import { getDeployStore } from "@netlify/blobs";

export const onPostBuild = async () => {

const uploads = getDeployStore("file-uploads");

const { data, metadata } = await uploads.getWithMetadata("my-key");

if (entry === null) {

console.log("Could not find entry");

} else {

console.log("Data:", data);

console.log("Country:", metadata.country);

}

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

// Mock implementation of a system for locally persisting blobs and their etags

const cachedETag = getFromMockCache("my-key");

const uploads = getStore("file-uploads");

// Get entry from the blob store only if its ETag is different from the one you

// have locally, which means the entry has changed since you last retrieved it.

// Compare the whole value including surrounding quotes and any weakness prefix.

const { data, etag } = await uploads.getWithMetadata("my-key", {

etag: cachedETag,

});

if (etag === cachedETag) {

// `data` is `null` because the local blob is fresh

return new Response("Still fresh");

}

// `data` contains the new blob, store it locally alongside the new ETag

writeInMockCache("my-key", data, etag);

return new Response("Updated");

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

// Mock implementation of a system for locally persisting blobs and their etags

const cachedETag = getFromMockCache("my-key");

const uploads = getStore("file-uploads");

// Get entry from the blob store only if its ETag is different from the one you

// have locally, which means the entry has changed since you last retrieved it.

// Compare the whole value including surrounding quotes and any weakness prefix.

const { data, etag } = await uploads.getWithMetadata("my-key", {

etag: cachedETag,

});

if (etag === cachedETag) {

// `data` is `null` because the local blob is fresh

return new Response("Still fresh");

}

// `data` contains the new blob, store it locally alongside the new ETag

writeInMockCache("my-key", data, etag);

return new Response("Updated");

};

You can use object metadata to create client-side expiration logic. To delete blobs you consider expired, do the following:

  1. set your objects with metadata that you can base the expiration logic on, such as a timestamp
  2. getWithMetadata to check if an object is expired
  3. delete the expired object

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const uploads = getStore("file-uploads");

const key = "my-key";

// Set the entry with an `expiration` metadata property

await uploads.set(key, await req.text(), {

metadata: {

expiration: new Date("2024-01-01").getTime()

}

});

// Read the entry and compare the `expiration` metadata

// property against the current timestamp

const entry = await uploads.getWithMetadata(key);

if (entry === null) {

return new Response("Blob does not exist");

}

const { expiration } = entry.metadata;

// If the expiration date is in the future, it means

// the blob is still fresh, so return it

if (expiration && expiration < Date.now()) {

return new Response(entry.data);

}

// Delete the expired entry

await uploads.delete(key);

return new Response("Blob has expired");

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const uploads = getStore("file-uploads");

const key = "my-key";

// Set the entry with an `expiration` metadata property

await uploads.set(key, await req.text(), {

metadata: {

expiration: new Date("2024-01-01").getTime()

}

});

// Read the entry and compare the `expiration` metadata

// property against the current timestamp

const entry = await uploads.getWithMetadata(key);

if (entry === null) {

return new Response("Blob does not exist");

}

const { expiration } = entry.metadata;

// If the expiration date is in the future, it means

// the blob is still fresh, so return it

if (expiration && expiration < Date.now()) {

return new Response(entry.data);

}

// Delete the expired entry

await uploads.delete(key);

return new Response("Blob has expired");

};

Retrieves the metadata for an object, if the object exists.

This method is useful to check if a blob exists without actually retrieving it and having to download a potentially large blob over the network.

await store.getMetadata(key, { consistency, etag, type })

A Promise that resolves with an object containing the following properties:

If an object with the given key is not found, a Promise that resolves with null is returned.

This example shows how you might read metadata from user-generated submissions that have been previously uploaded to Netlify Blobs.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

// Extracting key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

const entry = await uploads.getMetadata(key);

if (entry === null) {

return new Response("Blob does not exist");

}

return Response.json({

etag: entry.etag,

metadata: entry.metadata

});

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

// Extracting key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

const entry = await uploads.getMetadata(key);

if (entry === null) {

return new Response("Blob does not exist");

}

return Response.json({

etag: entry.etag,

metadata: entry.metadata

});

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const uploads = getDeployStore("file-uploads");

const entry = await uploads.getMetadata("my-key");

console.log(entry.etag, entry.metadata);

};

Returns a list of blobs in a given store.

await store.list({ directories, paginate, prefix })

A Promise that resolves with an object containing the following properties:

This example shows how you might list all blobs in a given store, logging the key and etag of each entry.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const uploads = getStore("file-uploads");

const { blobs } = await uploads.list();

// [ { etag: "\"etag1\"", key: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" }, { etag: "\"etag2\"", key: "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed" } ]

console.log(blobs);

return new Response(`Found ${blobs.length} blobs`);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const uploads = getStore("file-uploads");

const { blobs } = await uploads.list();

// [ { etag: "\"etag1\"", key: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" }, { etag: "\"etag2\"", key: "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed" } ]

console.log(blobs);

return new Response(`Found ${blobs.length} blobs`);

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const uploads = getDeployStore("file-uploads");

const { blobs } = await uploads.list();

// [ { etag: "\"etag1\"", key: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" }, { etag: "\"etag2\"", key: "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed" } ]

console.log(blobs);

};

Optionally, you can group blobs together under a common prefix and then browse them hierarchically when listing a store. This is similar to grouping files in a directory. To browse hierarchically, do the following:

  1. Group keys hierarchically with the / character in your key names.
  2. List entries hierarchically with the directories parameter.
  3. Drill down into a specific directory with the prefix parameter.

Take the following set of keys as an example:

cats/shorthair.jpg

cats/longhair.jpg

dogs/beagle.jpg

dogs/corgi.jpg

bird.jpg

By default, list will return all five keys.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const animals = getStore("animals");

const { blobs } = await animals.list();

// [

// { etag: "\"etag1\"", key: "cats/shorthair.jpg" },

// { etag: "\"etag2\"", key: "cats/longhair.jpg" },

// { etag: "\"etag3\"", key: "dogs/beagle.jpg" },

// { etag: "\"etag4\"", key: "dogs/corgi.jpg" },

// { etag: "\"etag5\"", key: "bird.jpg" },

// ]

console.log(blobs);

return new Response(`Found ${blobs.length} blobs`);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const animals = getStore("animals");

const { blobs } = await animals.list();

// [

// { etag: "\"etag1\"", key: "cats/shorthair.jpg" },

// { etag: "\"etag2\"", key: "cats/longhair.jpg" },

// { etag: "\"etag3\"", key: "dogs/beagle.jpg" },

// { etag: "\"etag4\"", key: "dogs/corgi.jpg" },

// { etag: "\"etag5\"", key: "bird.jpg" },

// ]

console.log(blobs);

return new Response(`Found ${blobs.length} blobs`);

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const animals = getDeployStore("animals");

const { blobs } = await animals.list();

// [

// { etag: "\"etag1\"", key: "cats/shorthair.jpg" },

// { etag: "\"etag2\"", key: "cats/longhair.jpg" },

// { etag: "\"etag3\"", key: "dogs/beagle.jpg" },

// { etag: "\"etag4\"", key: "dogs/corgi.jpg" },

// { etag: "\"etag5\"", key: "bird.jpg" },

// ]

console.log(blobs);

};

To list entries hierarchically, set the directories parameter to true.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const animals = getStore("animals");

const { blobs, directories } = await animals.list({ directories: true });

// [ { etag: "\"etag5\"", key: "bird.jpg" } ]

console.log(blobs);

// [ "cats", "dogs" ]

console.log(directories);

return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const animals = getStore("animals");

const { blobs, directories } = await animals.list({ directories: true });

// [ { etag: "\"etag5\"", key: "bird.jpg" } ]

console.log(blobs);

// [ "cats", "dogs" ]

console.log(directories);

return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`);

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const animals = getDeployStore("animals");

const { blobs, directories } = await animals.list({ directories: true });

// [ { etag: "\"etag5\"", key: "bird.jpg" } ]

console.log(blobs);

// [ "cats", "dogs" ]

console.log(directories);

};

To drill down into a directory and get a list of its items, set the prefix parameter to the directory name.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const animals = getStore("animals");

const { blobs, directories } = await animals.list({

directories: true,

prefix: "cats/",

});

// [ { etag: "\"etag1\"", key: "cats/shorthair.jpg" }, { etag: "\"etag2\"", key: "cats/longhair.jpg" } ]

console.log(blobs);

// [ ]

console.log(directories);

return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const animals = getStore("animals");

const { blobs, directories } = await animals.list({

directories: true,

prefix: "cats/",

});

// [ { etag: "\"etag1\"", key: "cats/shorthair.jpg" }, { etag: "\"etag2\"", key: "cats/longhair.jpg" } ]

console.log(blobs);

// [ ]

console.log(directories);

return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`);

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const animals = getDeployStore("animals");

const { blobs, directories } = await animals.list({

directories: true,

prefix: "cats/",

});

// [ { etag: "\"etag1\"", key: "cats/shorthair.jpg" }, { etag: "\"etag2\"", key: "cats/longhair.jpg" } ]

console.log(blobs);

// [ ]

console.log(directories);

};

Note that the prefix includes a trailing slash. This ensures that only entries under the cats directory are returned. Without a trailing slash, other keys like catsuit would also be returned.

For performance reasons, the server groups results into pages of up to 1,000 entries. By default, the list method automatically retrieves all pages, meaning you’ll always get the full list of results.

To handle pagination manually, set the paginate parameter to true. This makes list return an AsyncIterator, which lets you take full control over the pagination process. This means you can fetch only the data you need when you need it.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const store = getStore("animals");

let blobCount = 0;

for await (const entry of store.list({ paginate: true })) {

blobCount += entry.blobs.length;

console.log(entry.blobs);

}

return new Response(`Found ${blobCount} blobs`);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const store = getStore("animals");

let blobCount = 0;

for await (const entry of store.list({ paginate: true })) {

blobCount += entry.blobs.length;

console.log(entry.blobs);

}

return new Response(`Found ${blobCount} blobs`);

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const store = getDeployStore("animals");

let blobCount = 0;

for await (const entry of store.list({ paginate: true })) {

blobCount += entry.blobs.length;

console.log(entry.blobs);

}

console.log(`Found ${blobCount} blobs`);

};

Returns a list of stores for a site. Does not include deploy-specific stores.

await listStores({ paginate })

A Promise that resolves with an object containing the following properties:

This example shows how you might list all stores for a given site.

import { listStores } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const { stores } = await listStores();

// [ "file-uploads", "json-uploads" ]

console.log(stores);

return new Response(`Found ${stores.length} stores`);

};

import { listStores } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

const { stores } = await listStores();

// [ "file-uploads", "json-uploads" ]

console.log(stores);

return new Response(`Found ${stores.length} stores`);

};

import { listStores } from "@netlify/blobs">

export const onPostBuild = async () => {

const { stores } = await listStores();

// [ "file-uploads", "json-uploads" ]

console.log(stores);

};

For performance reasons, the server groups results into pages of up to 1,000 stores. By default, the listStores method automatically retrieves all pages, meaning you’ll always get the full list of results.

To handle pagination manually, set the paginate parameter to true. This makes listStores return an AsyncIterator, which lets you take full control over the pagination process. This means you can fetch only the data you need when you need it.

import { listStores } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

let storeCount = 0;

for await (const entry of listStores({ paginate: true })) {

storeCount += entry.stores.length;

console.log(entry.stores);

}

return new Response(`Found ${storeCount} stores`);

};

import { listStores } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

let storeCount = 0;

for await (const entry of listStores({ paginate: true })) {

storeCount += entry.stores.length;

console.log(entry.stores);

}

return new Response(`Found ${storeCount} stores`);

};

import { listStores } from "@netlify/blobs">

export const onPostBuild = async () => {

const { stores } = await listStores({

paginate: true,

});

let storeCount = 0;

for await (const entry of stores) {

storeCount += entry.stores.length;

console.log(entry.stores);

}

console.log(`Found ${storeCount} stores`);

};

Deletes an object with the given key, if one exists.

A Promise that resolves with undefined.

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

// Extract key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

await uploads.delete(key);

return new Response("Blob has been deleted");

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions">

export default async (req: Request, context: Context) => {

// Extract key from URL.

const { key } = context.params;

const uploads = getStore("file-uploads");

await uploads.delete(key);

return new Response("Blob has been deleted");

};

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const uploads = getDeployStore("file-uploads");

await uploads.delete("my-key");

console.log("Blob has been deleted");

};

With file-based uploads, you can write blobs to deploy-specific stores after the build completes and before the deploy starts. This can be useful for authors of frameworks and other tools integrating with Netlify as it does not require a build plugin.

To make file-based uploads, place blob files in .netlify/blobs/deploy in your site’s base directory. Netlify uploads these files to blob storage maintaining their directory structure. Here is an example file tree:

.netlify/

├─ blobs/

| ├─ deploy/

│ | ├─ dogs/

│ │ | └─ good-boy.jpg

│ | ├─ cat.jpg

│ | └─ mouse.jpg

This uploads the following blobs:

To attach metadata to a blob, include a JSON file that prefixes the corresponding blob filename with $ and has a .json extension. For example:

.netlify/

├─ blobs/

| ├─ deploy/

│ | ├─ dogs/

│ │ | ├─ good-boy.jpg

│ │ | └─ $good-boy.jpg.json

│ | ├─ cat.jpg

│ | ├─ mouse.jpg

│ | └─ $mouse.jpg.json

This uploads the following blobs:

Metadata files must contain valid JSON or the deploy will fail. Here’s an example of valid JSON metadata:

By default, the Netlify Blobs API uses an eventual consistency model, where data is stored in a single region and cached at the edge for fast access across the globe. When a blob is added, it becomes globally available immediately. Updates and deletions are guaranteed to be propagated to all edge locations within 60 seconds.

You can configure this behavior and opt-in to strong consistency with the Netlify Blobs API, either for an entire store or for individual read operations. Netlify CLI always uses strong consistency.

Choosing the right consistency model depends on your use case and each option comes with tradeoffs:

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const store = getStore({ name: "animals", consistency: "strong" });

await store.set("dog", "🐶");

// This is a strongly-consistent read.

const dog = await store.get("dog");

return new Response(dog);

};

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const store = getStore("animals");

await store.set("dog", "🐶");

// This is an eventually-consistent read.

const dog1 = await store.get("dog");

// This is a strongly-consistent read.

const dog2 = await store.get("dog", { consistency: "strong" });

return new Response(dog1 + dog2);

};

In addition to using the Netlify Blobs API to list and get blobs, you can use the Netlify UI to browse and download blobs.

To explore and retrieve your site’s blobs:

  1. In the Netlify UI, go to the Blobs page for your project.

  2. If your site has more than one store, select the store of interest.

  3. Then, drill into directories to explore the blobs in the store or Download an individual blob to examine it.

You can store sensitive data with Netlify Blobs. To keep your data secure, we encrypt your blobs at rest and in transit.

Your blobs can only be accessed through your own site. You are responsible for making sure the code you use to access your blobs doesn’t allow data to leak. We recommend that you consider the following best practices:

Visit our security checklist for general security measures we recommend you consider for your site.

The namespaces you make with getStore are shared across all deploys of your site. This is required when using Netlify CLI and desirable for most use cases with functions and edge functions because it means that a new production deploy can read previously written data without you having to replicate blobs for each new production deploy. This also means you can test your Deploy Previews with production data. This does, however, mean that you should be careful to avoid scenarios such as a branch deploy deleting blobs that your published deploy depends on.

As mentioned above, build plugins and file-based uploads must write to deploy-specific stores. This requirement makes it so that a deploy that fails cannot overwrite production data.

To make a deploy-specific namespace with the Netlify Blobs API, use the getDeployStore method.

import { getDeployStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Generating a unique key for the entry.

const key = uuid();

const uploads = getDeployStore("file-uploads");

await uploads.set(key, await req.text());

return new Response(`Entry added with key ${key}`);

};

import { getDeployStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Generating a unique key for the entry.

const key = uuid();

const uploads = getDeployStore("file-uploads");

await uploads.set(key, await req.text());

return new Response(`Entry added with key ${key}`);

};

import { readFile } from "node:fs/promises";

import { getDeployStore } from "@netlify/blobs";

import { v4 as uuid } from "uuid";

export const onPostBuild = async () => {

// Reading a file from disk at build time.

const file = await readFile("some-file.txt", "utf8");

const uploads = getDeployStore("file-uploads");

await uploads.set(key, file);

console.log(`Entry added with key ${key}`);

};

In general, blobs in deploy-specific stores are managed by Netlify like other atomic deploy assets. This means they’re kept in sync with their relative deploys if you do a rollback and that they’re cleaned up with automatic deploy deletion.

However, downloading a deploy does not download deploy-specific blobs, and locking a published deploy does not prevent you from writing to associated deploy-specific stores.

By default, deploy-specific stores are located in the same region that your functions have been configured to run in. For a list of available regions, check out these region docs.

You can also manually specify which region to connect to, regardless of your function’s region, by passing the region as an option when using the getDeployStore method.

import { getDeployStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Generating a unique key for the entry.

const key = uuid();

const uploads = getDeployStore({ name: "file-uploads", region: "ap-southeast-2" });

await uploads.set(key, await req.text());

return new Response(`Entry added with key ${key}`);

};

import { getDeployStore } from "@netlify/blobs";

import type { Context } from "@netlify/edge-functions";

import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {

// Generating a unique key for the entry.

const key = uuid();

const uploads = getDeployStore({ name: "file-uploads", region: "ap-southeast-2" });

await uploads.set(key, await req.text());

return new Response(`Entry added with key ${key}`);

};

import { readFile } from "node:fs/promises";

import { getDeployStore } from "@netlify/blobs";

import { v4 as uuid } from "uuid";

export const onPostBuild = async () => {

// Reading a file from disk at build time.

const file = await readFile("some-file.txt", "utf8");

const uploads = getDeployStore({ name: "file-uploads", region: "ap-southeast-2" });

await uploads.set(key, file);

console.log(`Entry added with key ${key}`);

};

Keep the following requirements in mind while working with Netlify Blobs:

import { fetch } from "whatwg-fetch";

import { getStore } from "@netlify/blobs";

import type { Context } from "@netlify/functions">

export default async (req: Request, context: Context) => {

const uploads = getStore({ fetch, name: "file-uploads" });

const entry = await uploads.get("my-key");

return new Response(entry);

};

import { fetch } from "whatwg-fetch";

import { getDeployStore } from "@netlify/blobs">

export const onPostBuild = async () => {

const uploads = getDeployStore({

name: "file-uploads",

fetch

});

const entry = await uploads.get("my-key");

console.log(entry);

};

Keep the following rules in mind when creating namespaces and blobs:

Most characters use 1 byte

Most Unicode characters with UTF-8 encoding take 1 byte. So, for convenience, you can think of the above size limits as roughly a 64-character limit for store names and a 600-character limit for object keys. But, be aware that some characters take more than one byte. For example, à takes 2 bytes.

Keep the following limitations in mind when working with Netlify Blobs:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4