News & Announcements

Introducing Netlify Blobs Beta

At Netlify, we’re committed to building strong platform primitives that empower developers to do their best work and achieve more with less. From more control over caching for optimal performance with less reliance on framework internals to more powerful serverless computing with less API surface area, we continue to deliver on our commitment.

Today, we’re excited to announce Netlify Blobs, a general purpose data store built natively into the Netlify Composable Web Platform (CWP). It unlocks more complex and feature-rich applications with less configuration and maintenance.

Native data store

Data is the heart of every web application, and we want developers on Netlify to have access to the storage solutions that best fit their needs.

We believe that seamlessly integrating with the best-in-class vendors of each database type gives developers more control and flexibility than any one-size-fits-all solution we could ever prescribe.

But there’s a category of use cases that have become as ubiquitous as the web itself, and a data store for unstructured and binary data, built into the platform, can help developers take their products to market faster than ever. No setup required and no architecture lock-in.

Universal access, zero setup

With Netlify Blobs, you can create multiple stores for the different types of data in your application and access them from anywhere in the Netlify platform: your builds, functions, and edge functions.

True to our form, there is absolutely no setup involved in creating and starting to use a store — no provisioning stage, no configuration files, not even a button in a UI that you have to click.

You can get from zero to data with just two lines of code in an edge function:

import { getStore } from "@netlify/blobs"
import type { Context, Config } from "@netlify/edge-functions"

export default async (req: Request, context: Context) => {
  const store = getStore("lyrics")
  const data = await store.get("hey-jude")

  // "Na na na nananana"
  console.log(data)

  return new Response(data)
}

export const config: Config = {
  path: "/hey-jude"
}

Site-wide or deploy-specific

You can configure a store to exist at the site level, which means your data will be accessible from any deploy in any context. This lets you keep a persistent state that will remain available as you create new deploys or roll back to previous ones.

Alternatively, you can create a store that is scoped to one single deploy. This is perfect for augmenting a deploy at build time, since your data will be published, rolled back, and deleted in lockstep with the deploy it belongs to.

The example below shows how to achieve this using a Build Event Handler.

import { Blob } from "node:buffer"
import { readFileSync } from "node:fs"
import { getDeployStore } from "@netlify/blobs"
import { NetlifyIntegration } from "@netlify/sdk"

const integration = new NetlifyIntegration()

integration.addBuildEventHandler("onPreBuild", ({ constants }) => {
  const store = getDeployStore({
    siteID: constants.SITE_ID,
    token: constants.NETLIFY_API_TOKEN,
  })
  const blob = new Blob([readFileSync("./path/to/some/file")])

  await store.set("my-file", blob)
})

Use cases

Netlify Blobs is not a feature with one clear paved path, but rather a primitive that developers and frameworks can use as building blocks for an infinite number of applications.

Still, we wanted to share a few examples of powerful new patterns that you can unlock today.

Data store for functions

With Background Functions, you can trigger asynchronous serverless workflows on any Netlify site. This pattern is perfect for long-running operations like generating a site map, processing media assets, or sending emails in bulk.

Netlify Blobs is perfect for persisting the output of those computations:

import { getStore } from "@netlify/blobs"

export default async (req) => {
  const store = getStore("media")

  // Emulating a task that takes 60 seconds to complete
  setTimeout(async () => {
    await store.set("something-precious", "💎")
  }, 60_000)
}

Because reading from a store is as simple as writing, you can write a second function that checks, as part of a synchronous request/response flow, whether a background function execution has finished and what the output was:

import { getStore } from "@netlify/blobs"
import type { Config } from "@netlify/functions"

export default async (req) => {
  const store = getStore("media")
  const value = await store.get("something-precious")

  if (value === null) {
    return Response.json({
      ready: false
    });
  }

  return Response.json({
    ready: true,
    value
  })
}

export const config: Config = {
  path: "/poll"
}

You can also use Netlify Blobs with Scheduled Functions and write to a store the result of a computation that runs on a schedule:

import { getStore } from "@netlify/blobs"
import type { Config } from "@netlify/functions"

export default async (req) => {
  const store = getStore("daily-random-numbers")
  const key = new Date().toLocaleDateString()

  await store.set(key, Math.random().toString());
}

export const config: Config = {
  schedule: "@daily"
}

Programmable cache

Another powerful capability of Netlify Blobs is its ability to be used as a programmable cache for HTTP requests. If your application interacts with a third-party API that is slow, unreliable, or expensive, you may benefit from caching its responses so you call it less often.

The Netlify Blobs API is built on top of web platform standards, so it’s highly interoperable with the Fetch API. For example, you can retrieve a blob in most of the formats supported by the Request object, including a stream.

For maximum flexibility, you can attach arbitrary metadata to blobs, which you can use to persist status codes and response headers:

import { getStore } from "@netlify/blobs"
import { Config } from "@netlify/functions"

export default async (req) => {
  const store = getStore("api-cache")
  const apiURL = "<https://example.com/slow-api>"

  // Try to get the response from the store.
  const cached = await store.getWithMetadata(apiURL, { type: "stream" })

  // If it exists in the store, return it.
  if (cached !== null) {
    return new Response(cached.data, {
      headers: new Headers(cached.metadata.headers),
      status: cached.metadata.status,
    })
  }

  // If it doesn't exist, make the HTTP call and cache the
  // response in the store.
  const response = await fetch(apiURL)
  const body = await response.arrayBuffer()

  await store.set(apiURL, body, {
    metadata: {
      headers: [...response.headers],
      status: response.status
    }
  })

  return new Response(body, response)
}

export const config: Config = {
  path: "/call-external-api"
}

Processing uploads

If your application takes user submissions, like reviews on a product page or image files for a gallery, Netlify Blobs is a great fit for storing that data. When coupled with Functions or Edge Functions, it becomes very easy to create an endpoint to receive a form, validate the contents, and persist the data (if everything checks out):

import { getStore } from "@netlify/blobs"
import type { Config, Context } from "@netlify/functions"
import * as uuid from "uuid"

export default async (req: Request, context: Context) => {
  const key = uuid.v4()
  const store = getStore("uploads")
  const form = await req.formData()
  const file = form.get("file") as File

  if (file.type !== "image/png") {
    return new Response("Sorry, only PNGs are allowed", { status: 400 })
  }

  await store.set(key, file)

  return new Response(`Upload processed: ${key}`)
}

export const config: Config = {
  method: "POST",
  path: "/upload"
}

Now in public beta

Netlify Blobs is available today as a beta feature. It’s still under active development and it’s not perfect, but we believe in getting it into the hands of developers sooner, rather than later, because listening to your feedback is how we’ll make a better product.

We’re very excited with the capabilities we’ve showcased here, but we can’t wait to see the use cases that we haven’t even dreamed of that our community will put together.

There are no costs associated with Netlify Blobs during the beta period. We’ll announce the pricing model before it’s generally available, but it will be accessible on all plans (including Starter).

We invite you to follow our documentation and try Netlify Blobs today. Let us know about your experience through our support portal or our community forum.

Keep reading

Recent posts

How do the best dev and marketing teams work together?