netlify/context-and-tools

netlify-blobs

Store and retrieve unstructured data like file uploads, images, documents, JSON, and cache-like state with Netlify Blobs.

查看源码
仓库原始内容

按源仓库内容呈现,保留标题、案例、代码、表格、链接以及原文引用的演示图片。

Netlify Blobs

Modern syntax — import from @netlify/blobs, open a store, operate on it:

ts
import { getStore } from "@netlify/blobs";
const store = getStore("file-uploads");        // site-wide
await store.set(key, value, { metadata: { … } });
const entry = await store.get(key);            // null if missing

Deploy-specific isolation:

ts
import { getDeployStore } from "@netlify/blobs";
const store = getDeployStore("file-uploads");

Requires Fetch API (Node.js 18+). Functions written in Go cannot access Blobs. Not for per-user/transactional/relational data — use Netlify DB.

Footguns (read first)

  • Site-scoped stores (`getStore`) are shared across ALL deploy contexts. Code on a deploy preview reads, overwrites, and deletes production data. Never run destructive tests or seed throwaway data from previews — use getDeployStore() or a context-specific store name for isolation.
  • Site-wide stores do NOT follow your functions region. getStore defaults to us-east-2 regardless of where your functions run — no error or warning is raised. To use another region you must pass region on every getStore call for that store (reads, writes, deletes); a call that omits it hits us-east-2 and won't see data held elsewhere. Changing a store's region does not migrate data.
  • Last write wins. No concurrency control. Do not build counters, balances, or read-modify-write logic on a blob key — even with onlyIfMatch retries. That's transactional data; use Netlify DB.
  • No built-in access control. The serving function is the gate. Default to private: gate reads behind an authenticated function rather than exposing blobs publicly. Treat user input as unsafe — don't serve arbitrary caller-supplied keys; scope keys with something callers can't tamper with.
  • Eventual consistency by default — updates/deletions take up to 60s to propagate. Pass consistency: "strong" if a read must see the latest write immediately (slower reads).
  • When an operation fails, surface the error and read the function logs. Do not invent REST endpoints or side-channel APIs to retry.

Store selection

  • getStore(name) — site-wide; persists across deploys, readable from all contexts.
  • getDeployStore(name) — scoped to one deploy; use for isolation and for any write from a Build Plugin or file-based upload.
  • Build Plugins: can read from any of the site's stores, but can write only to deploy-specific stores (getDeployStore).

Both accept a positional form getStore(name, { region, siteID, token }) / getDeployStore(name, { deployID, region, siteID, token }) or an object form getStore({ name, consistency, region, siteID, token, fetch }). siteID, deployID, and token are set automatically inside Functions/Edge Functions/Build Plugins; supply them explicitly only to override (e.g. siteID of another site you own). region is auto-set only for getDeployStore (defaults to your functions region); for getStore it is not auto-set and defaults to us-east-2. Site ID = API site_id = NETLIFY_SITE_ID = the UI's Project ID.

Common tasks

Persist an upload (Function):

ts
import { getStore } from "@netlify/blobs";
import type { Context } from "@netlify/functions";
import { v4 as uuid } from "uuid";

export default async (req: Request, context: Context) => {
  const form = await req.formData();
  const file = form.get("file") as File;
  const uploads = getStore("file-uploads");
  await uploads.set(uuid(), file, {
    metadata: { country: context.geo.country.name }
  });
  return new Response("Submission saved");
};

Persist JSON — use setJSON:

ts
const uploads = getStore("json-uploads");
await uploads.setJSON(key, data, { metadata: { … } });

Read a blob (null if missing):

ts
const entry = await uploads.get(key);
if (entry === null) return new Response("Not found", { status: 404 });
return new Response(entry);

Read with metadata:

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

Delete / delete a whole store:

ts
await uploads.delete(key);
const { deletedBlobs } = await uploads.deleteAll(); // 0 if store didn't exist

API surface

Store-opening: getStore, getDeployStore, listStores (imported from @netlify/blobs). Store instance methods: get, getWithMetadata, getMetadata, set, setJSON, list, delete, deleteAll.

`set(key, value, { metadata, onlyIfMatch, onlyIfNew })`value is ArrayBuffer | Blob | string. Overwrites by default. Resolves { modified, etag }. `setJSON(key, value, { metadata, onlyIfMatch, onlyIfNew })` — same, value any JSON-serializable. `get(key, { consistency, type })`type one of text (default) / json / arrayBuffer / blob / stream. Resolves the value, or null if missing. `getWithMetadata(key, { consistency, etag, type })` — resolves { data, etag, metadata }, or null if missing. If etag matches the passed value, data is null (cache still fresh). `getMetadata(key, { consistency, etag, type })` — resolves { metadata, etag }, or null if missing. Check existence without downloading the blob. `list({ directories, paginate, prefix })` — resolves { blobs: [{ etag, key }], directories: string[] }. `listStores({ paginate })` — resolves { stores: string[] }. Does not include deploy-specific stores. `delete(key)` — resolves undefined. `deleteAll()` — resolves { deletedBlobs }; deleting a store is deleting all its blobs.

Atomic conditional writes

  • onlyIfNew: true — write only if the key does not exist.
  • onlyIfMatch: etag — write only if current ETag matches (optimistic concurrency).
  • Inspect the returned modified boolean to detect success/failure.
ts
const { modified } = await emails.set("jane@netlify.com", "Jane Doe", { onlyIfNew: true });
if (!modified) return new Response("Email already exists", { status: 400 });

(These are for single-key create-if-absent / compare-and-set, not for building transactional counters.)

Listing hierarchically

Group keys with /. list({ directories: true }) returns top-level directories plus root blobs. Drill in with prefixthe prefix must include a trailing slash ("cats/"), or keys like catsuit also match.

ts
const { blobs, directories } = await animals.list({ directories: true });
const cats = await animals.list({ directories: true, prefix: "cats/" });

Pagination

Server pages up to 1,000 entries (list) / 1,000 stores (listStores). Handled automatically by default; pass paginate: true for an AsyncIterator:

ts
for await (const entry of store.list({ paginate: true })) {
  console.log(entry.blobs);
}

Conditional requests / local caching

Pass a cached etag to getWithMetadata/getMetadata; if it matches, data is null (your copy is fresh). Compare the whole value including surrounding quotes and any weakness prefix.

Configuration

Consistency

Default is eventual (single-region, edge-cached; propagation within 60s). Opt into strong per store or per read:

ts
const store = getStore({ name: "animals", consistency: "strong" }); // store level
const dog = await store.get("dog", { consistency: "strong" });      // operation level

The Netlify CLI always uses strong consistency.

Regions

Valid regions (a smaller set than the function regions): us-east-1, us-east-2, eu-central-1, ap-southeast-1, ap-southeast-2.

  • Deploy-specific stores (getDeployStore) default to your functions region; region is auto-set in Functions/Edge Functions/Build Plugins. Override explicitly:
ts
  const uploads = getDeployStore({ name: "file-uploads", region: "ap-southeast-2" });
  • Site-wide stores (getStore) default to us-east-2 and do not follow your functions region. region is never auto-set here.
ts
  const profiles = getStore({ name: "user-profiles", region: "eu-central-1" });

Gotcha — pass `region` on every call. A site-wide store only reaches non-default-region data if every getStore call (reads, writes, deletes) passes the same region. Omit it and the call silently uses us-east-2 — no error is raised. Changing a store's region does not migrate data: the store appears empty in the new region while the original data stays in the old one. To move data, copy each entry to a store opened in the new region, then delete from the old.

Custom fetch

If you can't use Node.js 18, supply your own fetch:

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

File-based uploads (deploy-specific stores)

For framework/tool authors integrating without a build plugin. Place blob files under .netlify/blobs/deploy in the site's base directory; Netlify uploads them (preserving directory structure) after the build, before the deploy.

Netlify deletes `.netlify/blobs/deploy` before each build — files committed to the repo are NOT uploaded. You must create blob files during the build (build command or plugin).

Attach metadata with a sibling JSON file prefixing the blob filename with $ and ending .json:

.netlify/blobs/deploy/
├─ dogs/
│  ├─ good-boy.jpg
│  └─ $good-boy.jpg.json
├─ cat.jpg
└─ mouse.jpg      (no metadata)

Metadata files must be valid JSON or the deploy fails. Requires continuous deployment or CLI deploys.

Deploy-specific store lifecycle

  • Kept in sync on rollback; cleaned up with automatic deploy deletion.
  • Downloading a deploy does NOT download deploy-specific blobs.
  • Locking a published deploy does NOT prevent writing to its deploy-specific stores.

Expiration (no built-in TTL)

Roll your own: set with a timestamp in metadata → getWithMetadata to check → delete if expired.

CLI

netlify blobs:list/get/set/delete exist for inspection — see the CLI blobs command reference for details. The CLI always uses strong consistency and requires a site-wide store.

Local development

Netlify Dev uses a sandboxed local store: no file-based uploads, and you cannot read production data locally.

Constraints

  • Store names: no / or :, max 64 bytes.
  • Keys: non-empty, cannot start with /, any Unicode, max 600 bytes.
  • Object max 5 GB; metadata max 2 KB. (Byte limits, not char counts — some UTF-8 chars are multi-byte.)
  • Blobs encrypted at rest and in transit; accessible only through your own site.
  • Not part of Netlify's HIPAA-compliant hosting offering.
  • Review any third-party build plugin's code before trusting it with blob access.

Migration (@netlify/blobs 6.5.0 → 7.0.0)

Site-wide stores written with v6.5.0 or earlier become inaccessible after upgrading (namespacing change). Migrate per store with the latest Netlify CLI:

sh
netlify recipes blobs-migrate YOUR_STORE_NAME

Migrated stores are accessible with v7.0.0+.

<!-- system: agent-context/blobs/system.md — human-owned, merged by ctx-gen; edit system.md, not this section -->

Netlify house rules (blobs)

These are org conventions, not docs facts — merged into the rendered skill by ctx-gen and never generated. Owned by the skills maintainer.

  1. Blobs is not a database. For dynamic, per-user, or transactional data,

use Netlify DB — Blobs is for objects, files, and cache-like state.

  1. When a store operation fails, surface the error and read the function

logs — do not invent REST endpoints or side-channel APIs to retry.

  1. netlify blobs:list/get/set/delete exist for inspection; the CLI

reference is their source of truth — link, don't restate.

  1. Blobs have no built-in access control — the serving function is the gate.

When in doubt, default to private: gate reads behind an authenticated function rather than exposing blobs publicly.

  1. Site-scoped stores are shared across ALL deploy contexts — code on a

deploy preview reads, overwrites, and deletes production data. Never run destructive tests or seed throwaway data from previews; use getDeployStore() or a context-specific store name for isolation.

  1. Don't build counters, balances, or read-modify-write logic on a blob key —

even with onlyIfMatch retries. That's transactional data; use Netlify DB.

  1. Build plugins: state BOTH halves — they can read from any of the site's

stores, but write only to deploy-specific stores (getDeployStore).

来自同一仓库

更多 Skills

全部 Skills
netlify
社区

netlify-config

Configure Netlify builds and routing via netlify.toml, redirects, and headers. Use when setting a build command or publish directory, adding redirects or rewrites or proxies, adding an SPA fallback rewrite, setting custom response headers or basic auth, managing environment variables and secrets, scoping vars per deploy context, marking a var as secret, disabling secret scanning, configuring functions bundling, ignoring builds, or wiring up a monorepo or JavaScript SPA on Netlify.

安装量
1
GitHub Stars
37
最近更新
9月18日
netlify
社区

netlify-database

Zero-config Postgres for Netlify apps via @netlify/database — querying data from Functions/Edge Functions, writing schema migrations, setting up Drizzle ORM, local dev with netlify dev, database branches for deploy previews, and migrating an existing Postgres project onto Netlify. Use when adding a database, building a contact form or CRUD API, writing SQL migrations, wiring up Drizzle, running netlify database commands, testing with a local Postgres, or switching from Neon/Supabase/RDS to Netlify Database.

安装量
1
GitHub Stars
37
最近更新
9月18日
netlify
社区

netlify-frameworks

Deploy and configure web frameworks on Netlify — build settings and SSR/edge adapters plus local platform emulation and env vars. Use when setting up or fixing a framework deploy (Next.js / Astro / Nuxt / SvelteKit / Remix / React Router / TanStack Start / SolidStart / Gatsby / Angular / Vite / Express / Hydrogen / Hugo / Eleventy / Vue / React), adding SSR or edge functions or middleware wired to Netlify context, fixing SPA redirect and catch-all rules, setting a build command or publish directory, or debugging "why isn't my env var updating" and framework build failures.

安装量
1
GitHub Stars
37
最近更新
9月18日
netlify
社区

netlify-functions

Write, configure, and deploy Netlify serverless functions in TypeScript, JavaScript, or Go. Use this when adding an API endpoint or backend route, adding a contact form handler, wiring auth or Identity signup/login hooks, building streaming or AI-proxy responses, scheduling cron jobs, running long background jobs (batch processing/scraping), reacting to deploy or form events, setting up rate limiting or region/memory config, or reading environment variables and secrets inside a function. Covers file locations, the Request/Context/Response handler shape, path routing, config options, and local testing with netlify dev.

安装量
1
GitHub Stars
37
最近更新
9月18日