somewhere.techHow it works

A project database, or Postgres?

Both are relational databases. The useful difference is where you want the setup and policy work to live. somewhere.tech joins a managed database to your app's deploy and identity contract, so a new app has a working data layer on the first deploy. PostgreSQL gives you its full ecosystem and semantics. You do not have to pick once and live with it: a project can also attach a PostgreSQL database that you own, and use both.

Start on the managed database

It is the default because it comes with the parts of a data layer you would otherwise build and maintain: row permissions declared once on the table and enforced on ordinary scoped operations, a typed browser client generated from that declaration, db/schema.ts as a file your agent reads and changes, and nothing to operate — no connection string, pool, migration runner or second bill. It fits ordinary product data: accounts, orders, content, messages, and bounded relational work.

Reach for PostgreSQL when the reason is concrete

The data or the SQL already lives there. You need an extension or a behaviour the managed engine does not have — PostGIS, deep pgvector tuning, a specific driver. Heavy analytical scans are the workload. Or existing tooling and reporting are part of how you work, and it speaks PostgreSQL.

What changes in practice

DecisionManaged project databaseYour own PostgreSQL, attached
SetupOne database per project, activated and connected by the platform.You own the account and the database. You choose the region, credentials, connection behavior, and recovery plan; the platform stores the connection and hands it to your functions.
SchemaDeclare managed tables in source, or use developer-side migrations for hand-managed SQL tables.Use your chosen migration framework and deployment process.
Row accessDeclared structured operations can scope rows to the signed-in user. Server functions still own elevated authorization decisions.Your handler owns it. The managed declarations are NOT applied to this SQL — verify the caller and put the restriction in a parameterized WHERE, or use PostgreSQL row-level-security policies.
SQLJoins, indexes, constraints, transactions, JSON, triggers, CTEs, and full-text search, with documented engine semantics.Full Postgres behavior, extensions, types, drivers, and tooling.
Scale shapeUp to 10 GB in one project database; writes within a project are serialized; not built for heavy analytical scans.Your provider's compute, storage, replicas, pooling, and scaling choices.
BillingPart of your somewhere.tech plan.Attaching is included on every somewhere.tech plan, including Free. Your provider then bills you directly under its own pricing and limits; nothing is metered or marked up here.
Leavingdb_dump exports schema and rows. Moving that data INTO PostgreSQL is a real conversion pass you inspect and verify.PostgreSQL-native backups and migration tools. Attaching one does not require moving anything first.

Compatibility is deliberately specific. somewhere.tech accepts a documented Postgres-flavored syntax subset, including numbered placeholders and common JSON operators. It is not PostgreSQL: extensions, types, ordering details, division behavior, and some SQL forms differ.

Attaching your own PostgreSQL

This is live today, not a plan. A project can attach ONE external PostgreSQL database that you own — a Neon database. Attaching is available on every somewhere.tech plan, including the Free one; that is a statement about our plans, not about Neon's. Neon keeps its own pricing and its own limits, bills you directly, and nothing about it is metered or marked up here. It is a pass-through, not a resold or managed service.

You attach it from the CLI, and the connection is bound into the deployed release, so it takes effect on your next deploy:

somewhere postgres connect --project my-app --neon-project <neon-project-id>
somewhere postgres attach <neon-project-id> --project my-app   or   somewhere postgres create --project my-app
somewhere postgres status --project my-app

Your deployed functions then query it through sw.postgres, which is the official driver's callable — the result IS the array of rows. Two things follow from it being your database: your handler owns row permissions there, because the managed declarations do not reach this SQL; and it sits ALONGSIDE the managed database rather than replacing it, so there is no migration to do before you attach. Keep accounts and product data where they are, and put the PostgreSQL workload on PostgreSQL.

You get PostgreSQL's ecosystem and semantics, but this binding is a driver with its own shape, so check the feature you need against it rather than assuming every transport feature is present. The clearest example: transaction([...]) applies a FIXED LIST of statements atomically, and interactive transactions — open one, read, branch in JavaScript, commit later — are not available through it. The full contract, including connect, attach, create, status and disconnect, role and row-level-security guidance, and how to measure your own workload, is in the PostgreSQL topic of the product reference: run somewhere docs postgres, or ask an agent for docs({ topic: 'postgres' }).

Is one faster? Measure your workload

Which is quicker depends on your data, your queries and where things sit, so the number worth having is yours. We have published no managed-versus-attached benchmark, and older figures comparing two ways of reaching the MANAGED database say nothing about PostgreSQL. A comparison that means something uses isolated data you can hammer with the same row counts and the same INDEXES on both sides, the same statements and the same permission semantics — if one side scopes rows to the caller, the other needs that WHERE too, or you are timing two different questions — and reports cold and warm separately.

The known limits may decide it without a measurement: the managed database holds up to 10 GB per project, serializes writes within a project, and is not built for heavy analytical scans. If your workload lives there, attach PostgreSQL and move on.

You can change your mind

Start on the managed database when the integrated contract saves work. Attach PostgreSQL when a concrete reason shows up, and keep both if that is the honest answer. The decision should follow your workload, not a claim that one database is universally better.