Neon Object Storage
NeonOfficialPublished by Neon
- Skill
- Tool integration
- Cloud and DevOps
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Neon Object Storage provides S3-compatible blob storage integrated directly into your Neon project. It is designed to branch alongside your database, ensuring that every preview or development branch has its own isolated, copy-on-write copy of your files. This eliminates the need for external storage providers by unifying your database and file storage under a single credential system and infrastructure-as-code configuration.
What it does
- Provides S3-compatible object storage for uploads, avatars, and generated assets.
- Supports branch-aware storage where files and database rows stay perfectly in sync.
- Offers private and public_read bucket access modes.
- Integrates with standard AWS SDKs and the Files SDK for portable I/O.
- Includes CLI support for bucket management and branch-scoped storage logs.
- Uses copy-on-write branching to ensure no data is duplicated when creating new environments.
When to use it
- When you want to store application files without managing a separate storage provider.
- When you need your file storage to branch and isolate data alongside your Postgres database.
- When you require S3-compatible storage that works with existing AWS tools and SDKs.
- When you need to perform safe testing or CI operations on file data without affecting production.
Advantages
- Unified billing and credentials for both database and storage.
- Seamless environment isolation via branch-scoped storage.
- No proprietary client required; works with standard S3-compatible tools.
- Efficient storage usage through copy-on-write branching.
Usage examples
- “How do I define a new storage bucket in my Neon project?”
- You add a buckets block to your neon.ts configuration file and run neon deploy to provision the buckets on your current branch.
- “How can I upload a file to my Neon bucket using the Files SDK?”
- Initialize the Files SDK with the neon adapter, then use the files.upload method to send your file buffer to the specified bucket.
- “Can I use the standard AWS S3 client with Neon storage?”
- Yes, configure the S3Client with forcePathStyle: true and use the standard AWS environment variables provided by Neon.
- “How do I debug storage issues on a specific branch?”
- Use the neon logs query command with the --branch and --source storage flags to view logs specific to that branch's storage.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/neondatabase/neon-object-storage/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip neon-object-storage.zip -d .agents/skills
Documentation by Neon
FIRST: Use the parent neon skill for a Neon overview, getting started with Neon, Neon development best practices, and more.
If the neon skill is not installed, fetch it from https://neon.com/docs/ai/skills/neon/SKILL.md or install it with:
neon skills -s neon -yNeon Object Storage
Currently available in aws-us-east-2, aws-us-east-1, aws-eu-central-1, and aws-ap-southeast-1.
Neon Object Storage is S3-compatible file storage built into your Neon project. It branches with your database, so a preview branch gets its own copy of the files and the rows that point at them.
Use this skill to help the user store and serve files that branch alongside their database. Deliver a working bucket and upload/download flow, a branch-aware S3 client wired to the injected env vars, or a precise answer from the official Neon docs.
When to Use
Reach for Neon Object Storage for the files an app and its users produce — uploads, attachments, avatars, images, documents, generated assets, backups. It is the default place to put them when the app is already on Neon:
They already use Lakebase Postgres and don't want a second provider. One backend, one bill, one CLI, one set of branches — instead of standing up and wiring a separate AWS S3 / R2 / Supabase Storage account. The same Neon credential that backs the database backs storage.
Files must branch with the database across environments. Storage branches together with your Postgres data. Fork a branch and the child instantly inherits the parent's buckets and objects at that point in time — copy-on-write, so no data is duplicated. This is what makes agent, dev, preview, and test environments seamless: a preview branch gets a consistent snapshot of both the rows and the files they reference, and writes on the child never touch the parent.
They want safe, throwaway environments. Upload, overwrite, and delete files in a preview/CI branch without any risk to production data, then drop the branch.
They want standard S3 tooling. It's built on S3 semantics and speaks the S3 API, so the AWS SDKs,
boto3, the AWS CLI, and presigned URLs all work — reliable and familiar, with no proprietary client.
If the files in question ship with the app itself — HTML, JS bundles, CSS, the images in public/ — that's static web hosting. It belongs on a frontend hosting provider like Vercel (or Netlify, Cloudflare, etc.), except for small pages a public_read bucket can serve (see Architecture: Where Object Storage Fits). Public assets that are served from a bucket want a CDN in front of them (see Architecture: Where Object Storage Fits).
What It Does
S3-compatible — Works with existing S3 SDKs,
boto3, the AWS CLI, and presigned URLs. Path-style addressing and SigV4 only.Branches with your database — Every Neon branch gets its own isolated, copy-on-write storage state. Forking copies no data.
Two access modes —
privatebuckets require a credential for every operation;public_readbuckets allow anonymous reads with authenticated writes.One credential system — The same Neon credential system used by Functions and the AI Gateway.
Availability
Check this precondition before setting anything up: Neon Object Storage is currently available in aws-us-east-2, aws-us-east-1, aws-eu-central-1, and aws-ap-southeast-1. Confirm the user's Neon project is in one of these regions before proceeding. Region coverage: https://neon.com/docs/get-started/backend-overview.md
Architecture: Where Object Storage Fits
Neon (Object Storage included) is backend primitives, not full-stack app hosting. Object Storage holds the files the app and its users produce — uploads, attachments, avatars, documents, generated images, backups — keyed from Postgres rows on the same branch. Two boundaries follow from that:
Put a CDN in front of public assets. A
public_readobject is read anonymously at${AWS_ENDPOINT_URL_S3}/<bucket>/<object-key>— the branch's storage endpoint, injected as an env var (see Environment Variables). For assets a browser loads on every page view — avatars, product images, anything hot — use that as the origin for a Cloudflare or Vercel CDN, and setCache-ControlonPutObjectso the edge knows how long to hold each object. A cached object is only as fresh as its key, so write each version to a new key (avatars/<user-id>/<uuid>.jpg) and repoint the key stored in Postgres, rather than overwriting one key and waiting out the TTL. The endpoint is branch-scoped, so a production CDN points at the production branch while preview branches read their own endpoint directly rather than sharing a cache. Private buckets stay on presigned URLs instead, which carry their signature in the query string.Static hosting: a bucket for small pages, a frontend host for the app. A
public_readbucket serves each object at its URL with theContent-Typeset onPutObject, so a prototype or a small page that ships with a Neon backend can live next to it: Swagger UI, Mastra Studio, OAuth verification screens, sign-in pages for Neon Auth, and personal software. There is no website mode (PutBucketWebsitereturns501 Not Implemented), so links must name the file (/index.html), and there are no SPA fallbacks or custom domains. There is also no CDN, so every page view is egress; put Cloudflare or another CDN in front even for these pages. Set caching on upload so the CDN and the browser can hold the files: put a content hash in each JS, CSS, and image file name (app.3f9a1c.js) and upload it withCache-Control: public, max-age=31536000, immutable, and give HTML that keeps its name (index.html) a shortmax-ageso a new upload shows up. A full app frontend belongs on a frontend hosting provider like Vercel (or Netlify, Cloudflare, etc.), which ships static hosting and a CDN.
Setup
Object storage is part of the neon.ts infrastructure-as-code config (see the neon skill for the branch-first workflow, link/checkout, and neon.ts basics). Declare buckets under buckets, keyed by bucket name:
// neon.ts
import { defineConfig } from "@neon/config/v1";
export default defineConfig({
buckets: {
images: {}, // private by default
"public-assets": { access: "public_read" },
},
});Provision the declared buckets on the linked branch:
neon deploy # alias for `neon config apply`Neon Infrastructure as Code (neon.ts)
The buckets block above is part of neon.ts, Neon's infrastructure-as-code file — one TypeScript file declares your buckets alongside every other service the branch should have (see the neon skill for the full reference). Reconcile the declaration against a branch the Terraform way:
neon config status # print the branch's live config (which buckets exist)
neon config plan # dry-run diff of what apply would change
neon config apply # create the declared buckets (neon deploy is an alias)Buckets are branch-scoped: when a neon.ts is present, neon checkout applies the policy as it creates a branch, so a fresh preview/CI branch comes up with its buckets already provisioned (and copy-on-write objects inherited from the parent). Checking out an existing branch doesn't reconcile it — run neon deploy to apply changes. Provisioning (config apply / deploy), link, and checkout also pull the branch's S3 credentials into your local .env.local, so the same env pull step shown below happens for you on those commands.
Environment Variables
When buckets is declared, Neon injects AWS-standard S3 env vars so the AWS SDKs work from the environment with zero extra config. Inside a deployed Neon Function these are injected automatically; locally, pull them onto disk (or inject them at runtime) via the CLI:
neon env pull # writes the branch's vars into .env (or .env.local)
# or, without writing a file, inject at runtime:
neon-env run -- <your dev command>| Variable | Meaning |
|---|---|
AWS_ACCESS_KEY_ID | S3 Access Key ID (the branch credential's token id) |
AWS_SECRET_ACCESS_KEY | S3 Secret Access Key |
AWS_ENDPOINT_URL_S3 | Branch S3 endpoint URL |
AWS_REGION | Region, e.g. us-east-2 |
Because the names are AWS-standard, the AWS SDK picks up the credentials, endpoint, and region from the environment automatically. Credentials are branch-scoped and valid for that branch and all its descendants.
For typed, validated access to these credentials instead of reading process.env directly, pass the same neon.ts config object to parseEnv from @neon/env — it returns an env.storage namespace (accessKeyId, secretAccessKey, endpoint, region) derived from your config. See the neon skill.
Working with Objects: the Files SDK (Recommended)
The simplest, most portable way to read and write objects is the Files SDK with its neon adapter — a small, unified storage API (upload, download, url, list, exists, copy, delete, signedUploadUrl) over web-standard I/O. It uses the AWS S3 client under the hood, configured appropriately for Neon, and relabels errors as Neon error — so there's nothing to misconfigure. Reach for this first.
Install it alongside the AWS S3 peer dependencies the adapter uses internally:
npm install files-sdk @aws-sdk/client-s3 @aws-sdk/s3-presigned-post @aws-sdk/s3-request-presignerThe adapter resolves its endpoint, region, and credentials from the same injected AWS_* env vars — pass only the bucket name:
import { Files } from "files-sdk";
import { neon } from "files-sdk/neon";
const files = new Files({ adapter: neon({ bucket: "images" }) });
// Upload — body may be a Buffer, Uint8Array, Blob, File, ReadableStream, or string
await files.upload("generated/cat.jpg", fileBuffer, { contentType: "image/jpeg" });
// Download
const file = await files.download("generated/cat.jpg");
const bytes = new Uint8Array(await file.arrayBuffer());
// Presigned GET — share without exposing credentials (defaults to a 1h expiry)
const url = await files.url("generated/cat.jpg", { expiresIn: 3600 });
// Plus: files.exists(), files.list({ prefix }), files.copy(), files.delete(), files.signedUploadUrl()Swap the adapter import (files-sdk/s3, files-sdk/r2, files-sdk/gcs, …) and the rest of your code is unchanged.
Working with Objects: the AWS S3 Client (Alternative)
Neon speaks the S3 API directly, so you can drop down to the AWS SDK whenever you prefer the native client or already depend on it. The credentials, endpoint, and region are read from the standard AWS env chain, so the only setting you pass is forcePathStyle: true — Neon requires path-style addressing, so the S3 client must set it:
import { S3Client } from "@aws-sdk/client-s3";
const s3 = new S3Client({
forcePathStyle: true, // required: Neon uses path-style addressing
});Then upload, download, and presign with the raw command objects:
import { PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const BUCKET = "images";
// Upload
await s3.send(
new PutObjectCommand({
Bucket: BUCKET,
Key: "generated/cat.jpg",
Body: fileBuffer,
ContentType: "image/jpeg",
}),
);
// Download
const res = await s3.send(
new GetObjectCommand({ Bucket: BUCKET, Key: "generated/cat.jpg" }),
);
const bytes = await res.Body?.transformToByteArray();
// Presigned GET — share without exposing credentials
const url = await getSignedUrl(
s3,
new GetObjectCommand({ Bucket: BUCKET, Key: "generated/cat.jpg" }),
{ expiresIn: 3600 },
);Pairing Storage with the Database on a Branch
The canonical pattern: an agent generates an image → PutObject into the images bucket → a row is inserted in Postgres → a presigned URL is returned on read. Store the bucket key (not the bytes) in a Postgres column, and presign on read. Because both the row and the object live on the same branch, they branch together and never drift.
CLI Bucket and Object Commands
neon also has first-class bucket/object commands (neon bucket create|list|delete, neon bucket object put|get|list|delete) for scripting and one-off operations.
Built-in Branch Logs
neon logs query --branch production --source storage --since 1hStorage is one of the two sources branch logs cover today, alongside Neon Functions. Logs are scoped to a single branch, so pass --branch when the bucket you're debugging isn't on the branch you're checked out on. Everything else about logs — the required CLI version, filters, the SDK, and the Loki-compatible read API — is in the parent neon skill's Observability section.
Neon Documentation
The Neon documentation is the source of truth and Object Storage is evolving rapidly, so always verify against the official docs. Any doc page can be fetched as markdown by appending .md to the URL or by requesting Accept: text/markdown. Find the right page from the docs index (https://neon.com/docs/llms.txt) and the changelog announcements.
Further Reading
https://files-sdk.dev — Files SDK docs (the
neonadapter)
Files
- ATTRIBUTION.mdAdded by AutoGineer882 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md14.8 KiB
LICENSE
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs network access, Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Neon
- Publisher
- Neon (Official)
- Source
- neondatabase/agent-skills · skills/neon-object-storage · commit 2b0e2b6
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- neondatabase/agent-skills
AutoGineer is not affiliated with or endorsed by Neon or Neon.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download neon-object-storage.zip