惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
T
Threat Research - Cisco Blogs
量子位
Last Week in AI
Last Week in AI
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
爱范儿
爱范儿
D
Docker
人人都是产品经理
人人都是产品经理
S
SegmentFault 最新的问题
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
A
About on SuperTechFans
P
Proofpoint News Feed
博客园 - 司徒正美
Recent Announcements
Recent Announcements
I
InfoQ
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
Webroot Blog
Webroot Blog
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
SecWiki News
SecWiki News
Attack and Defense Labs
Attack and Defense Labs
Hacker News: Ask HN
Hacker News: Ask HN
AI
AI
博客园_首页
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recorded Future
Recorded Future
T
Tailwind CSS Blog
MyScale Blog
MyScale Blog
T
Tenable Blog
宝玉的分享
宝玉的分享
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
C
Check Point Blog
S
Security Affairs
L
LINUX DO - 最新话题
大猫的无限游戏
大猫的无限游戏
Scott Helme
Scott Helme
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
月光博客
月光博客
Y
Y Combinator Blog

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management
Postgres WASM by Snaplet and Supabase
Mark Burggraf · 2022-10-03 · via Supabase Blog

Postgres WASM by Snaplet and Supabase

Today we're open sourcing postgres-wasm with our friends at Snaplet.

postgres-wasm is a PostgreSQL server that runs inside a browser. It provides a full suite of features, including persisting state to browser, restoring from pg_dump, and logical replication from a remote database.

We're not the first to run Postgres in the browser - that title belongs to the team at Crunchy Data who shared their version of this on HN a month ago. It's awesome, and we wanted an open source version, so we teamed up with Snaplet build it. Let's explore how it's built, and some extra features we've added.

🐈 Who's Snaplet?

Snaplet gives developers production-accurate data and preview databases that they can code against, so they can focus on shipping.

Checkout out how you can use Snaplet to clone Supabase environments.

Before we get into the technical details, try it out yourself (warning: it will download ~30MB):

wasm.supabase.com

To run it locally:


_11

# From Snaplet Repo

_11

git clone git@github.com:snaplet/postgres-wasm.git

_11

cd postgres-browser/packages/pg-browser

_11

npx serve

_11

_11

# From Supabase Fork

_11

git clone git@github.com:supabase-community/postgres-wasm.git

_11

cd postgres-wasm

_11

git checkout web

_11

cd packages/supabrowser

_11

npx serve


And open a browser at localhost:3000.

Our demo version has a few neat features!

  • Postgres 14.5, psql, pg_dump, etc.
  • Save & restore state to/from a file.
  • Save & restore Postgres state to/from the browser storage (IndexedDB).
  • Quick start from a state file or fully reboot the emulator.
  • Memory configuration options from 128MB to 1024MB.
  • Adjust the font size for the terminal.
  • Upload files to the emulator (including database dumps and CSVs).
  • Download files from the emulator.
  • Outgoing network connectivity from the emulator to the internet.
  • Incoming network tunnel to postgres port 5432 inside the emulator.

That's a good question. postgres-wasm is currently about 30mb. So at this stage, running Postgres in the browser isn't great for general use-cases. It has a lot of potential though. Some ideas we'll be playing with over the next few months:

  • Documentation: for tutorials and demos.
  • Offline data: running it in the browser for an offline cache, similar to sql.js or absurd-sql.
  • Offline data analysis: using it in a dashboard for offline data analysis and charts.
  • Testing: testing PostgreSQL functions, triggers, data modeling, logical replication, etc.
  • Dev environments: use it as a development environment — pull data from production or push new data, functions, triggers, views up to production.
  • Snapshots: create a test version of your database with sample data, then take a snapshot to send to other developers.
  • Support: send snapshots of your database to support personnel to demonstrate an issue you're having.

We've divided in our repository into three folders: a virtual machine, a web application, and a network proxy.

Virtual Machine (VM)#

We create an embeddable Virtual Machine (VM) using Buildroot. Our VM is a stripped-down Linux build with Postgres installed.

See source code.

Web application#

Next, we need to run the VM inside our browser. How? WASM. We use v86 to run our VM inside the browser. Our demo application is very simple - plain HTML and some basic styling.

See source code.

Network proxy#

Running Postgres in a browser is great, but connecting to it with PgAdmin is even better. Unfortunately browsers block TCP network access to the VM. To circumvent this, we proxy the traffic through websockets. We run a fork of Websockproxy which allows the emulator to talk to the internet by converting data sent over a websocket port into TCP packets. Our fork of Websockproxy adds the ability to tunnel into the Postgres server.

See source code.

There were a lot of hurdles that we discovered throughout the development of postgres-wasm.

WASM#

The first thing to point out is that our implementation isn't pure WASM. We attempted to compile Postgres for WASM directly from source, but it was more complicated that we anticipated.

Crunchy's HN post provided some hints about the approach they took, which was to virtualize a machine in the browser. We pursued this strategy too, settling on v86 which emulates an x86-compatible CPU and hardware in the browser.

PostgreSQL 14 segfault errors#

We quickly had PostgreSQL 13.3 running using an outdated version of Buildroot. But version PG14+ wouldn't start, giving a segfault during initialization. We tried:

  • manually copying build files for PG14 into the older version(s) of Buildroot
  • building with (many) newer copies of Buildroot
  • adjusting kernel parameters and environment settings such as the amount of memory allocated to the emulator, etc.

Eventually, Fabian, the creator of v86 suggested we turn off JIT compilation for v86 and that solved the issue. He narrowed it down to a bug in v86 and is pushing an update that will fix it. Switching Postgres from posix to sysv memory management also solved the issue for the current release of V86.

Optimizing startup time and image size#

With PG14 running in the emulator, we shifted our focus to performance. The image size for the emulator was too big for a browser-based tool. Even with our best efforts, a compressed snapshot was over 30mb - a fairly large payload to download before you can see any interaction.

We solved this by booting only a minimal Linux image and then dynamically loading the rest of the VM over HTTPS after initialization.

We achieve this by mounting a compressed 9P filesystem in the VM. 9P provides a Python script which takes a filesystem folder, renames every file an 8-character name and produces a filesystem.json file representing a nested structure with files, original file names, sizes, etc. We then copy this compressed output to the VM. We modified the kernel command line and v86 boot parameters to boot directly from the 9P filesystem, and even put our kernel file into the p9 filesystem. All non-essential files are loaded asynchronously over HTTPS in the browser as needed.

The initial state was smaller, but still 15-20mb in size. We discussed this with Fabian who pointed us towards the page_poison=on kernel parameter. This parameter allowed us to clear caches before creating the snapshots, by forcing Linux to write arbitrary bytes on freed memory instead of random bytes, so unused memory is compressed much more efficiently.

The end result of all these changes? The compressed initial state file is about 12mb - including a running network state and Postgres 14.4 running with psql loaded.

We experimented without Postgres started too - this produced an even smaller initial state but the time to initialize Postgres was usually longer than the time to download a few extra megabytes. We opted for a faster startup time.

Additionally, without a running state you'd hit a performance penalty every time you refreshed the page, since Postgres would need to be initialized each time. In our current version, after the initial state is downloaded and cached by the browser the VM feels almost instant on refresh.

Networking#

Networking was particularly difficult to solve. For security reasons, browsers only support access to a nominal set of ports. In short, browsers speak “80/443” and Postgres speaks “5432” so there was no way for our Postgres to communicate with the outside world.

WASM isn't much help here - a WebAssembly module running in the browser is generally not able to do anything outside itself, except for calling functions exposed from JavaScript.

Browsers provide another connection option for us however: Websockets. The nice thing about websocket connections is that they are persistent, so all we needed was to figure out how to proxy the virtual machine traffic through a websocket connection.

The VM includes an emulated network card (ne2k-pci) and a proxy_url startup parameter which points to an external server running a websocket proxy (i.e. on the internet). The websocket proxy establishes connections via a websocket port, then accepts raw ethernet packets. It turns those raw packets into TCP/IP packets and routes them between the Internet and the VM.

With our tunnel established, we could now send network traffic to the outside world. For example, try “starting” the network on the VM, "exiting" out of psql (cmd+D), and then run ping 1.1.1.1.

Most v86 VM's use an open proxy at wss://relay.widgetry.org/ based on websockproxy. This proxy allows the VM to communicate with the outside world. It can handle all the basic use-cases like loading data from other PostgreSQL databases using pg_dump and psql, or operating as read-only replica of another database.

However, this proxy doesn't allow incoming traffic to be routed into a VM running locally on a laptop. For instance, you can't connect a local PgAdmin4 to the PostgreSQL instance running inside your browser. So we forked the proxy and added nginx to provide a reverse proxy.

The reverse proxy listens on a range of ports, mapping each port to the VM at a specific private address you want to reach. The simple solution was to take the last 2 segments of the private IP and map it to a port number. So if your private IP is 10.5.6.123, you connect to the proxy on port 6123 and that points you to PostgreSQL (running on port 5432) on private IP 10.5.6.123. Shortened addresses are padded, so 10.5.6.2 maps to port 6002 and 10.5.6.44 to port 6044.

Sending commands to the emulator from the browser UI#

Once the emulator is running, in the words of Fabian, “it runs as a black box process”, and the only way to communicate between the UI and the operating system running in the emulator is through serial0_send to send keystrokes over the emulated serial port, or through the create_file function which uploads a file to the running emulator.

To restart the network after restoring a state file, we need to run a short script to unbind and re-bind the emulated network card (so it gets a new mac address and thus a unique private IP address at the proxy), and then a standard network restart command. We could run this script by sending keystrokes to the emulator, but that's clumsy. What if the user is at a psql prompt? Then we'd send \! script_command. But if they're at an OS prompt, that won't work.

We solved the issue by creating a folder called \inbox and added a listener to the folder. When files arrive there, if the file ends in .sh (a shell script), we chmod +x that file, execute it, then delete it. That allows us to run commands “in the background” without upsetting the UI.

If you want to do something very cool, you can connect to another user's Postgres instance that they are running in their browser. Here are the steps:

  1. Find a friend (sometimes the first step is the hardest)
  2. Tell them to go to wasm.supabase.com
  3. Tell them to “Start Network” and get their Network URL
  4. Have them set a password on their database ALTER ROLE postgres WITH PASSWORD 'my_password';
  5. On your own machine, open a terminal and run psql postgres://postgres:my_password@proxy.wasm.supabase.com:<PORT>
  6. And you're in! You're now connecting to a remote Postgres instance, inside a VM, inside a browser, from a terminal on your own computer.

Database Replication

Even more mind-blowing - it's possible to replicate data from an online PostgreSQL database (for example, a Supabase project) to PostgreSQL running inside your browser, and vice-versa using Postgres's logical replication. The steps are no different than any other Postgres database - just use the proxy URL as the target.

For now, this is very experimental - but it has a lot of potential. If you want to get involved, please reach out to us or the team at Snaplet. The work they're doing over at Snaplet is incredible, and we've had a blast collaborating with them.