Community编程与开发github.com

neondatabase/neon-object-storage

Neon Object Storage 是兼容 S3 的对象存储服务,与您的 Neon 项目分支绑定,让文件和数据库行在开发、预览、预发布和生产环境中保持同步。

neon-object-storage 是什么?

Neon Object Storage 是一项公开测试版功能(目前支持 us-east-2 和 eu-central-1 区域),它提供了 S3 兼容的对象存储,并与您的 Neon 项目分支紧密集成。每个分支都拥有独立的、写时复制的存储状态,因此分叉分支时不会复制任何实际数据,从而在开发、预览、CI/CD 和生产环境之间提供一致的数据库和文件快照。该技能指导用户通过基础设施即代码(neon.ts)声明 bucket,并利用 Neon CLI (`neon deploy`、`neon env pull`)自动化部署和凭据注入。它支持两种访问模式:private(需要认证)和 public_read(允许匿名读取),并原生兼容 AWS SDK、boto3、AWS CLI 以及预签名 URL。技能推荐使用 Files SDK(`files-sdk` 的 `neon` 适配器)作为主要编程接口,同时也提供了直接使用 AWS S3 客户端的替代方案。此外,它还通过 `neon` CLI 和分支日志提供了 bucket/对象命令,以及与 Lakebase Postgres 紧密结合的最佳实践,例如在 Postgres 行中存储对象键,并在读取时预签名 URL,确保文件在分支间不会漂移。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/neondatabase/agent-skills/tree/main/skills/neon-object-storage

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

首先:使用父级 neon 技能获取 Neon 概述、入门指南、Neon 开发最佳实践等更多信息。

如果尚未安装 neon 技能,请从 https://neon.com/docs/ai/skills/neon/SKILL.md 获取,或通过以下命令安装:

npx skills add neondatabase/agent-skills --skill neon

Neon Object Storage

这是一个公开测试版功能,目前可在 us-east-2 和 eu-central-1 区域使用。

Neon Object Storage 是 S3 兼容的对象存储服务,它会随您的项目分支一起分支:每个分支都获得独立的隔离存储状态,因此文件和数据库行在开发、预览、预发布和生产环境中保持同步。

使用此技能帮助用户存储和提供与数据库一起分支的文件。提供一个可用的 Bucket 和上传/下载流程、一个连接到注入环境变量的分支感知型 S3 客户端,或从官方的 Neon 文档中提供精确答案。

何时使用

当您的应用及其用户产生文件(上传、附件、头像、图片、文档、生成的资源、备份)时,可以考虑使用 Neon Object Storage。当应用已经运行在 Neon 上时,它是存放这些文件的默认位置:

  • 他们已经在使用 Lakebase Postgres,并且不想使用第二个提供商。 一个后端、一张账单、一个 CLI、一组分支——无需设置并连接独立的 AWS S3 / R2 / Supabase Storage 账户。支持数据库的同一 Neon 凭证也支持存储。
  • 文件必须跨环境与数据库保持同步。 存储与您的 Postgres 数据一起分支。分叉一个分支,子分支会立即继承父分支在该时间点的 Bucket 和对象——写时复制,因此不会重复数据。这使得代理、开发、预览和测试环境无缝衔接:预览分支获得行和它们引用的文件的一致快照,且子分支上的写入永远不会影响父分支。
  • 他们想要安全、可丢弃的环境。 在预览/CI 分支中上传、覆盖和删除文件,而不会对生产数据造成任何风险,然后删除该分支。
  • 他们想要标准的 S3 工具。 它基于 S3 语义构建并使用 S3 API,因此 AWS SDK、boto3、AWS CLI 和预签名 URL 都可以工作——可靠且熟悉,无需专有客户端。

如果相关的文件随应用本身一起交付——HTML、JS 包、CSS、public/ 中的图片——那是静态 Web 托管,应属于 Vercel、Netlify 或 Cloudflare。从 Bucket 提供的公共资源需要一个 CDN 前置(参见 架构:对象存储的定位)。

功能

  • S3 兼容——与现有的 S3 SDK、boto3、AWS CLI 和预签名 URL 一起使用。仅支持路径风格寻址和 SigV4。
  • 随您的数据库一起分支——每个 Neon 分支都获得独立的、写时复制的存储状态。分叉不会复制任何数据。
  • 两种访问模式——private 类型的 Bucket 每次操作都需要凭证;public_read 类型的 Bucket 允许匿名读取,但写入仍需认证。
  • 统一的凭证系统——与 Neon Functions 和 AI Gateway 使用相同的 Neon 凭证系统。

可用性

在开始设置之前,请检查此前提条件:Neon Object Storage 是一个公开测试版功能,目前仅在 us-east-2 和 eu-central-1 区域可用。在继续之前,请确认用户的 Neon 项目位于其中一个区域。

架构:对象存储的定位

Neon(包括 Object Storage)是后端原语,而非全栈应用托管。Object Storage 存放应用及其用户产生的文件——上传、附件、头像、文档、生成的图片、备份——通过同一分支上的 Postgres 行进行键关联。由此得出两个边界:

  • 为公共资源前置一个 CDN。 public_read 对象可以在 $AWS_ENDPOINT_URL_S3/<bucket>/<object-key> 处匿名读取——这是分支的存储端点,作为环境变量注入(见环境变量)。对于浏览器每次页面加载都会请求的热点资源——头像、产品图片等——请使用该端点作为 Cloudflare 或 Vercel CDN 的源,并在 PutObject 时设置 Cache-Control,以便边缘节点知道每个对象应缓存多久。缓存对象的新鲜度仅取决于其键,因此请将每个版本写入一个新键(avatars/<user-id>/<uuid>.jpg),并更新 Postgres 中存储的键,而不是覆盖同一个键并等待 TTL 过期。端点是分支范围的,因此生产环境的 CDN 指向生产分支,而预览分支则直接读取自己的端点,而不是共享一个缓存。私有 Bucket 则改用预签名 URL,其签名包含在查询字符串中。
  • 在其他地方托管应用本身。 检入到仓库的任何内容——HTML、JS 包、CSS,以及随 public/ 交付的图片和字体——应属于 Vercel、Netlify 或 Cloudflare,以及与之相关的索引文档、SPA 回退和自定义域名。Neon 没有网站模式来提供它们:PutBucketWebsite 返回 501 Not Implemented。

设置

对象存储是 neon.ts 基础设施即代码配置的一部分(请参阅 neon 技能了解分支优先的工作流程、link/checkout 和 neon.ts 基础)。在 preview.buckets 下声明 Bucket,以 Bucket 名称为键:

// neon.ts
import { defineConfig } from "@neon/config/v1";

export default defineConfig({
  preview: {
    buckets: {
      images: {}, // 默认为 private
      "public-assets": { access: "public_read" },
    },
  },
});

在链接的分支上配置声明的 Bucket:

neon deploy   # `neon config apply` 的别名

Neon 基础设施即代码(neon.ts)

上面的 preview.buckets 块是 neon.ts 的一部分,它是 Neon 的基础设施即代码文件——一个 TypeScript 文件声明您的 Bucket,以及该分支应具有的每项其他服务(请参阅 neon 技能获取完整参考)。像 Terraform 那样将声明与分支进行协调:

neon config status   # 打印分支的实时配置(存在哪些 Bucket)
neon config plan     # 预览 apply 将要产生的变更的差异
neon config apply    # 创建声明的 Bucket(neon deploy 是别名)

Bucket 是分支范围的:当存在 neon.ts 时,neon checkout 在创建分支时应用该策略,因此一个全新的预览/CI 分支启动时,其 Bucket 已经配置好(并且通过写时复制从父分支继承了对象)。检出一个现有分支不会重新协调它——运行 neon deploy 以应用更改。配置(config apply / deploy)、link 和 checkout 也会将分支的 S3 凭证提取到您的本地 .env.local 文件中,因此下面展示的 env pull 步骤会为您自动执行。

环境变量

当声明了 preview.buckets 时,Neon 会注入AWS 标准的 S3 环境变量,因此 AWS SDK 无需额外配置即可从环境中工作。在部署的 Neon Function 内部,这些变量会自动注入;在本地,通过 CLI 将它们拉取到磁盘上(或在运行时注入):

neon env pull            # 将分支的变量写入 .env(或 .env.local)
# 或者,不写入文件,在运行时注入:
neon-env run -- <your dev command>
变量含义
AWS_ACCESS_KEY_IDS3 访问密钥 ID(分支凭证的令牌 ID)
AWS_SECRET_ACCESS_KEYS3 秘密访问密钥
AWS_ENDPOINT_URL_S3分支 S3 端点 URL
AWS_REGION区域,例如 us-east-2

由于名称是 AWS 标准的,AWS SDK 会自动从环境中获取凭证、端点和区域。凭证是分支范围的,对该分支及其所有后代有效。

为了对这些凭证进行类型化、经过验证的访问,而不是直接读取 process.env,请将相同的 neon.ts 配置对象传递给 @neon/env 的 parseEnv——它会返回一个从您的配置派生的 env.storage 命名空间(accessKeyId、secretAccessKey、endpoint、region)。请参阅 neon 技能。

处理对象:Files SDK(推荐)

读写对象最简单、最可移植的方法是使用 Files SDK 及其 neon 适配器——这是一个小型、统一的存储 API(upload、download、url、list、exists、copy、delete、signedUploadUrl),使用基于 Web 标准的 I/O。它在内部使用 AWS S3 客户端,并已为 Neon 进行了适当配置,并将错误重新标记为 Neon error——因此不存在配置错误的风险。请优先考虑使用此方法。

将其与适配器内部使用的 AWS S3 对等依赖项一起安装:

npm install files-sdk @aws-sdk/client-s3 @aws-sdk/s3-presigned-post @aws-sdk/s3-request-presigner

适配器从相同的注入 AWS_* 环境变量中解析其端点、区域和凭证——只需传递 bucket 名称:

import { Files } from "files-sdk";
import { neon } from "files-sdk/neon";

const files = new Files({ adapter: neon({ bucket: "images" }) });

// 上传 — body 可以是 Buffer、Uint8Array、Blob、File、ReadableStream 或 string
await files.upload("generated/cat.jpg", fileBuffer, { contentType: "image/jpeg" });

// 下载
const file = await files.download("generated/cat.jpg");
const bytes = new Uint8Array(await file.arrayBuffer());

// 预签名 GET — 共享时不暴露凭证(默认过期时间为 1 小时)
const url = await files.url("generated/cat.jpg", { expiresIn: 3600 });

// 此外:files.exists()、files.list({ prefix })、files.copy()、files.delete()、files.signedUploadUrl()

只需切换适配器导入(files-sdk/s3、files-sdk/r2、files-sdk/gcs……),其余代码无需更改。

处理对象:AWS S3 客户端(替代方案)

Neon 直接通过 S3 API 通信,因此您可以随时降级到 AWS SDK,无论是您更喜欢原生客户端还是已经依赖于它。凭证、端点和区域从标准的 AWS 环境链中读取,因此您只需传递 forcePathStyle: true——Neon 需要路径风格寻址,因此 S3 客户端必须设置此项:

import { S3Client } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  forcePathStyle: true, // 必需:Neon 使用路径风格寻址
});

然后使用原始命令对象进行上传、下载和预签名:

import { PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const BUCKET = "images";

// 上传
await s3.send(
  new PutObjectCommand({
    Bucket: BUCKET,
    Key: "generated/cat.jpg",
    Body: fileBuffer,
    ContentType: "image/jpeg",
  }),
);

// 下载
const res = await s3.send(
  new GetObjectCommand({ Bucket: BUCKET, Key: "generated/cat.jpg" }),
);
const bytes = await res.Body?.transformToByteArray();

// 预签名 GET — 共享时不暴露凭证
const url = await getSignedUrl(
  s3,
  new GetObjectCommand({ Bucket: BUCKET, Key: "generated/cat.jpg" }),
  { expiresIn: 3600 },
);

在分支上将存储与数据库配对

典型的模式:代理生成图片 → PutObject 到 images Bucket → 在 Postgres 中插入行 → 读取时返回预签名 URL。将 Bucket 键(而不是字节)存储在 Postgres 列中,并在读取时进行预签名。由于行和对象都位于同一分支上,它们一起分支且永远不会漂移。

CLI Bucket 和对象命令

neon 还提供了一流的 Bucket/对象命令(neon bucket create|list|delete、neon bucket object put|get|list|delete),用于脚本编写和一次性操作。

内置分支日志

neon logs query --branch production --source storage --since 1h

存储是分支日志当前涵盖的两种来源之一,另一种是 Neon Functions。日志范围限定于单个分支,因此如果您要调试的 Bucket 不在您当前检出的分支上,请传递 --branch 参数。关于日志的所有其他内容——所需的 CLI 版本、过滤器、SDK 和 Loki 兼容的读取 API——都在父级 neon 技能的可观测性部分中。

Neon 文档

Neon 文档是事实来源,Object Storage 正在快速发展,因此务必对照官方文档进行验证。任何文档页面都可以通过将 .md 附加到 URL 或请求 Accept: text/markdown 头来获取为 Markdown 格式。从文档索引(https://neon.com/docs/llms.txt)和变更日志公告中找到正确的页面。

进一步阅读

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

neondatabase/claimable-postgres

Provision instant temporary Postgres databases via Claimable Postgres by Neon (neon.new) with no login, signup, or credit card. Supports REST API, CLI, and SDK. Use when users ask for a quick Postgres environment, a throwaway DATABASE_URL for prototyping/tests, or "just give me a DB now". Triggers include: "quick postgres", "temporary postgres", "no signup database", "no credit card database", "instant DATABASE_URL", "npx neon-new", "neon.new", "neon.new API", "claimable postgres API".

neondatabase/neon

>-

neondatabase/neon-ai-gateway

>-

neondatabase/neon-functions

>-

neondatabase/neon-postgres

Guides and best practices for working with Neon Serverless Postgres. Covers setup, connection methods, branching, autoscaling, scale-to-zero, read replicas, connection pooling, Neon Auth, and the Neon CLI, MCP server, REST API, TypeScript SDK, and Python SDK. Use when users ask about "Neon setup", "connect to Neon", "Neon project", "DATABASE_URL", "serverless Postgres", "Neon CLI", "neonctl", "Neon MCP", "Neon Auth", "@neondatabase/serverless", "@neondatabase/neon-js", "scale to zero", "Neon autoscaling", "Neon read replica", or "Neon connection pooling".

neondatabase/neon-postgres-branches

>-

neondatabase/neon-postgres-egress-optimizer

Diagnose and fix excessive Postgres egress (network data transfer) in a codebase. Use when a user mentions high database bills, unexpected data transfer costs, network transfer charges, egress spikes, "why is my Neon bill so high", "database costs jumped", SELECT * optimization, query overfetching, reduce Neon costs, optimize database usage, or wants to reduce data sent from their database to their application. Also use when reviewing query patterns for cost efficiency, even if the user doesn't explicitly mention egress or data transfer.

相关技能