Storage Release Notes

Last updated: Feb 23, 2026

  • Feb 19, 2026
    • Date parsed from source:
      Feb 19, 2026
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Private storage enters beta with a new get() API. You can upload and read private blobs by setting access: 'private', and use conditional gets with etag to avoid re-downloads. Returns a stream and blob metadata for easy streaming.

    Minor Changes

    04ca1f0: Add private storage support (beta), a new get() method, and conditional gets

    Private storage (beta)

    You can now upload and read private blobs by setting access: 'private' on put() and get(). Private blobs require authentication to access — they are not publicly accessible via their URL.

    New get() method

    Fetch blob content by URL or pathname. Returns a ReadableStream along with blob metadata (url, pathname, contentType, size, etag, etc.).

    Conditional gets with ifNoneMatch

    Pass an ifNoneMatch option to get() with a previously received ETag. When the blob hasn't changed, the response returns statusCode: 304 with stream: null, avoiding unnecessary re-downloads.

    Example

    import { put, get } from "@vercel/blob";
    // Upload a private blob
    const blob = await put("user123/avatar.png", file, { access: "private" });
    // Read it back
    const response = await get(blob.pathname, { access: "private" });
    // response.stream — ReadableStream of the blob content
    // response.blob — metadata (url, pathname, contentType, size, etag, ...)
    // Conditional get — skip download if unchanged
    const cached = await get(blob.pathname, {
      access: "private",
      ifNoneMatch: response.blob.etag,
    });
    if (cached.statusCode === 304) {
      // Blob hasn't changed, reuse previous data
    }
    

    Learn more: https://vercel.com/docs/vercel-blob/private-storage

    Original source Report a problem
  • Feb 6, 2026
    • Date parsed from source:
      Feb 6, 2026
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Minor Changes

    2b1cbbc: Add ifMatch option to del() for conditional deletes (optimistic concurrency control). Only works for single-URL deletes.

    Original source Report a problem
  • All of your release notes in one feed

    Join Releasebot and get updates from Vercel and hundreds of other software products.

  • Feb 4, 2026
    • Date parsed from source:
      Feb 4, 2026
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Vercel blob now supports ETag based conditional writes, returning etags on all blob operations and enabling ifMatch for optimistic concurrency. It introduces BlobPreconditionFailedError to handle mismatches and prevent overwrites.

    Minor Changes

    6c68442: Add ETag support for conditional writes (optimistic concurrency control)
    Return etag in all blob responses (put, copy, head, list, multipart)
    Accept ifMatch option in put/copy/createMultipartUpload for conditional writes
    Add BlobPreconditionFailedError for ETag mismatch (HTTP 412)

    Usage Example: Preventing Lost Updates

    When multiple users or processes might update the same blob concurrently, use ifMatch to ensure you don't overwrite someone else's changes:

    import { put, head, BlobPreconditionFailedError } from "@vercel/blob";
    // User 1: Read the current blob and get its ETag
    const metadata = await head("config.json");
    console.log(metadata.etag); // e.g., '"abc123"'
    // User 2: Also reads the same blob (same ETag)
    const metadata2 = await head("config.json");
    // User 1: Updates the blob with ifMatch
    // This succeeds because the ETag matches
    const result1 = await put(
      "config.json",
      JSON.stringify({ setting: "user1" }),
      {
        access: "public",
        allowOverwrite: true, // Required when updating existing blobs
        ifMatch: metadata.etag, // Only write if ETag still matches
      }
    );
    console.log(result1.etag); // New ETag: '"def456"'
    // User 2: Tries to update with their (now stale) ETag
    // This fails because User 1 already changed the blob
    try {
      await put("config.json", JSON.stringify({ setting: "user2" }), {
        access: "public",
        allowOverwrite: true,
        ifMatch: metadata2.etag, // Stale ETag - blob was modified!
      });
    } catch (error) {
      if (error instanceof BlobPreconditionFailedError) {
        // The blob was modified since we last read it
        // Re-fetch, merge changes, and retry
        const freshMetadata = await head("config.json");
        await put("config.json", JSON.stringify({ setting: "user2" }), {
          access: "public",
          allowOverwrite: true,
          ifMatch: freshMetadata.etag, // Use fresh ETag
        });
      }
    }
    

    Key Points

    • allowOverwrite: true: Required when updating an existing blob at the same path
    • ifMatch: Only performs the write if the blob's current ETag matches this value
    • Combined: "Overwrite, but only if the blob hasn't changed since I last read it"
    • ETags follow RFC 7232 format with surrounding quotes (e.g., "abc123")
    Original source Report a problem
  • Jan 23, 2026
    • Date parsed from source:
      Jan 23, 2026
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Patch Changes

    • e2de71a: Upgrade undici to fix security issue warning
    Original source Report a problem
  • Oct 24, 2025
    • Date parsed from source:
      Oct 24, 2025
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Patch Changes

    • 1dee5ab: Support Next.js v16 Cache Components even within proxy.ts (fka middleware.ts) - see #890

    The @vercel/edge-config v1.4.1 release added support for Next.js v16 cacheComponents, but did not support using @vercel/edge-config in Next.js's proxy.ts (fka middleware.ts) when the cacheComponents flag was enabled in next.config.ts. This releases fixes this issue so @vercel/edge-config can be used in any server side context in Next.js again.

    Original source Report a problem
  • Oct 22, 2025
    • Date parsed from source:
      Oct 22, 2025
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Patch Changes

    • 309509c: Adjust README
    Original source Report a problem
  • Sep 16, 2025
    • Date parsed from source:
      Sep 16, 2025
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Major update introduces a breaking change for onUploadCompleted in Client Uploads when not hosted on Vercel. On Vercel, the callbackUrl is inferred automatically. Non‑Vercel setups must provide callbackUrl and follow new env var guidance for local development.

    Major Changes

    0b8ead9: BREAKING CHANGE:
    To continue receiving onUploadCompleted callback once a file is uploaded with Client Uploads when not hosted on Vercel, you need to provide the callbackUrl at the onBeforeGenerateToken step when using handleUpload.
    When hosted on Vercel:
    No code changes required. The callbackUrl is inferred from Vercel system environment variables:
    In preview environment: VERCEL_BRANCH_URL when available, otherwise VERCEL_URL
    In production environment: VERCEL_PROJECT_PRODUCTION_URL
    If you're not hosted on Vercel or you're not using Vercel system environment variables, your will need to provide the callbackUrl:
    Before:

    await handleUpload({
      body,
      request,
      onBeforeGenerateToken: async (pathname) => {
        /* options */
      },
      onUploadCompleted: async ({ blob, tokenPayload }) => {
        /* code */
      },
    });
    

    After:

    await handleUpload({
      body,
      request,
      onBeforeGenerateToken: async (pathname) => {
        return { callbackUrl: 'https://example.com' }; // the path to call will be automatically computed
      },
      onUploadCompleted: async ({ blob, tokenPayload }) => {
        /* code */
      },
    });
    

    For local development:
    Set the VERCEL_BLOB_CALLBACK_URL environment variable to your tunnel URL:
    VERCEL_BLOB_CALLBACK_URL=https://abc123.ngrok-free.app
    See the updated documentation at https://vercel.com/docs/vercel-blob/client-upload to know more.
    Details:
    Before this commit, during Client Uploads, we would infer the callbackUrl at the client side level (browser) based on location.href (for convenience).
    This is wrong and allows browsers to redirect the onUploadCompleted callback to a different website.
    While not a security risk, because the blob urls are already public and the browser knows them, it still pose a risk of database drift if you're relying on onUploadCompleted callback to update any system on your side.

    Original source Report a problem
  • May 23, 2025
    • Date parsed from source:
      May 23, 2025
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Patch Changes

    • f65d3c9: copy, head and del can receive a blob url or pathname, until now it was not very clear.
    Original source Report a problem
  • May 22, 2025
    • Date parsed from source:
      May 22, 2025
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Minor Changes

    • 2b4acc3: feat(blob): Add support for custom headers in client upload method

    This change adds the ability to pass custom headers to the upload method in the client, which will be forwarded to the server endpoint specified by handleUploadUrl. This is particularly useful for sending authorization headers and solves issues like #796 and #420.

    Original source Report a problem
  • May 19, 2025
    • Date parsed from source:
      May 19, 2025
    • First seen by Releasebot:
      Feb 23, 2026

    Storage by Vercel

    Patch Changes

    • d3627fa: Update Vercel Blob API endpoint to a more efficient one
    Original source Report a problem

Related products