<?xml version="1.0" encoding="UTF-8" ?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" version="2.0"><channel><title>Joey Mezzacappa | CrunchyData Blog</title>
<atom:link href="https://www.crunchydata.com/blog/author/joey-mezzacappa/rss.xml" rel="self" type="application/rss+xml" />
<link>https://www.crunchydata.com/blog/author/joey-mezzacappa</link>
<image><url>https://www.crunchydata.com/build/_assets/default.png-W4XGD4DB.webp</url>
<title>Joey Mezzacappa | CrunchyData Blog</title>
<link>https://www.crunchydata.com/blog/author/joey-mezzacappa</link>
<width>256</width>
<height>256</height></image>
<description>PostgreSQL experts from Crunchy Data share advice, performance tips, and guides on successfully running PostgreSQL and Kubernetes solutions</description>
<language>en-us</language>
<pubDate>Wed, 24 Aug 2022 11:00:00 EDT</pubDate>
<dc:date>2022-08-24T15:00:00.000Z</dc:date>
<dc:language>en-us</dc:language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<item><title><![CDATA[ Crazy Idea to Postgres in the Browser ]]></title>
<link>https://www.crunchydata.com/blog/crazy-idea-to-postgres-in-the-web-browser</link>
<description><![CDATA[ We've got Postgres running in a web browser and lots of folks were curious how it was built. Joey goes through the prototyping steps. ]]></description>
<content:encoded><![CDATA[ <p>We <a href=https://www.crunchydata.com/blog/learn-postgres-at-the-playground>just launched</a> our <a href=https://www.crunchydata.com/developers/tutorials>Postgres Playground</a>. Running Postgres in the web browser was not exactly commonplace before, so naturally, people are wondering how it works.<p>It actually started as a fun weekend experiment. Here's a screenshot I saved, just moments after recovering from the initial "whoa, it's working!" effect.<p><img alt="Screenshot of PostgreSQL running in the Chrome web browser"loading=lazy src=/blog-assets/browser-pg/screenshot.webp><p>The next morning, I shared this screenshot in our internal Slack channel for web frontend engineering. Our mental gears began to turn as we imagined what might (and might not) be possible. After a bit of work, we built upon some interesting ideas, and this fun weekend hack evolved into what is now the <a href=https://www.crunchydata.com/developers/tutorials>Postgres Playground</a>!<p>This blog post focuses on how to run PostgreSQL in the web browser, but there are other interesting pieces involved in the playground as well. For example, the content in the tutorials actually lives in <a href=https://www.notion.so/>Notion</a> documents. There may be a blog post about that in the near future from one of my colleagues, so stay tuned!<h2 id=why><a href=#why>Why?</a></h2><p>I stumbled upon an interesting <a href=https://wasmer.io/posts/markdown-playgrounds-powered-by-wasm>blog post</a> about how Wasmer has a "Run in Playground" link for some Markdown fenced code blocks for a few of their <a href=https://wapm.io/>WAPM</a> packages. There was one in particular that <em>really</em> got my attention: <a href=https://wapm.io/sqlite/sqlite>SQLite</a>. On that page, there is a fenced code block with some SQL queries inside. If you click the "Run in Playground" button, it runs the query right there in the web browser with SQLite compiled to WebAssembly.<p>After running that SQLite query in my browser, I thought, "Can I do this with Postgres?".<p>The modern web browser is a very powerful platform, and this platform's capabilities are constantly increasing. However, WebAssembly still has some growing to do in some areas. After some quick research, I found that the web browser simply does not offer the networking features that Postgres needs. That would seem like a pretty big obstacle.<p><em><strong>However</strong>...</em><p>As I mentioned, the modern web browser is a very powerful platform. Let's just change the target platform to something other than WebAssembly, then run it in WebAssembly anyway like a rebel. 😎<h2 id=virtual-machines-in-the-browser><a href=#virtual-machines-in-the-browser>Virtual machines in the browser</a></h2><p>It's actually possible to emulate a PC <em>inside the web browser</em>! There have been quite a few implementations over the years. Some even started out in JavaScript, years before WebAssembly was an option. Here are a few that I found especially interesting:<table><thead><tr><th>Emulator<th>Architecture<tbody><tr><td><a href=https://github.com/nepx/halfix>Halfix</a><td>x86<tr><td><a href=https://bellard.org/jslinux/>JSLinux</a><td>x86 and RISC-V<tr><td><a href=https://github.com/s-macke/jor1k>jor1k</a><td>OpenRISC 1000<tr><td><a href=https://github.com/copy/v86>v86</a><td>x86<tr><td><a href=https://webvm.io/>WebVM</a><td>x86</table><p>I ended up choosing v86 for this. The author started the project in 2011, and it's still active. Many questions have been answered in the GitHub issues and discussions over the years. I'm definitely not an expert in Linux or virtualization, so being able to search the repo for answers was very helpful.<p>v86's performance also seemed to be among the best, compared to similar open source emulators that run in the browser. In early 2021, they merged a <a href=https://github.com/copy/v86/pull/388>Rust port + JIT</a> into the master branch, which provided a significant performance boost over the original JavaScript implementation.<h2 id=build><a href=#build>Build</a></h2><p>For this blog post, we'll use Alpine Linux. It's a lightweight Linux distribution and a very popular base for many Docker images. They also have a version with a slimmed-down kernel, optimized for virtual machines.<h3 id=install-alpine-linux><a href=#install-alpine-linux>Install Alpine Linux</a></h3><p>Note: You'll need to have QEMU installed.<p>Download the Alpine image that is optimized for VMs. We'll need the x86 (not x86_64) build.<pre><code class=language-shell>wget https://dl-cdn.alpinelinux.org/alpine/v3.16/releases/x86/alpine-virt-3.16.0-x86.iso
</code></pre><p>Create a disk image for the VM. I chose my disk size somewhat randomly, so feel free to make it larger if you'd like. You could probably make it smaller, but I'm not sure what the minimum size limit would be here.<pre><code class=language-shell>qemu-img create alpine.img 512M
</code></pre><p>Start the VM<pre><code class=language-shell>qemu-system-x86_64 \
  -m 256M \
  -cdrom alpine-virt-3.16.0-x86.iso \
  -drive file=alpine.img,format=raw
</code></pre><p>Note: Depending on your host machine, you may be able to get a performance boost by appending another argument to the command:<table><thead><tr><th>Host machine<th>Argument<tbody><tr><td>Linux with x86 CPU<td><code>-accel kvm</code><tr><td>macOS with x86 (Intel) CPU<td><code>-accel hvf</code><tr><td>macOS with Apple Silicon<td>None, but <a href=https://www.crunchydata.com/blog/postgresql-benchmarks-apple-arm-m1-macbook-pro-2020 title="Benchmark comparisons: Apple M1 vs. various x86 CPUs">your CPU is a beast anyway</a>.</table><p>When the VM has finished booting, log in as 'root'.<p>Run <code>setup-alpine</code>. For most of the setup questions, you can configure things to your liking, but these are important:<table><thead><tr><th>Question<th>Answer<tbody><tr><td><code>Which disk(s) would you like to use?</code><td><code>sda</code><tr><td><code>How would you like to use it?</code><td><code>sys</code><tr><td><code>WARNING: Erase the above disk(s) and continue?</code><td><code>y</code></table><p>After the installation has finished, use the <code>reboot</code> command to reboot the VM from the virtual hard disk image.<h3 id=install-postgres><a href=#install-postgres>Install Postgres</a></h3><p>After the VM has rebooted, log in as <code>root</code> again. We can now install and initialize Postgres.<pre><code class=language-shell>apk add postgresql --no-cache
/etc/init.d/postgresql setup
/etc/init.d/postgresql start
rc-update add postgresql
</code></pre><p>Now, a quick smoke test:<pre><code class=language-shell>su - postgres -c 'psql -c "SELECT version();"'
</code></pre><p>If it worked, you should see something like this:<pre><code class=language-text>                                                    version
----------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.4 on i586-alpine-linux-musl, compiled by gcc (Alpine 11.2.1_git20220219) 11.2.1 20220219, 32-bit
(1 row)
</code></pre><p>Note: On my machine, <code>psql</code> opened the version information in <code>less</code>, so I had to press <code>q</code> to exit that.<p>Now we can shut down the VM.<pre><code class=language-shell>poweroff
</code></pre><h2 id=run-the-vm-in-the-web-browser><a href=#run-the-vm-in-the-web-browser>Run the VM in the web browser</a></h2><ol><li>Go to <a href=https://copy.sh/v86/>v86's site</a>.<li>Scroll down to the "Setup" section.<li>For "Hard disk drive image", select the <code>alpine.img</code> file you created earlier.<li>Adjust "Memory size" to your liking. (I used 256 MB)<li>Click the "Start Emulation" button.</ol><p>Note: It will take a bit longer for the VM to boot. Running the VM in the web browser will not be as fast as it was in QEMU.<p>After it has finished booting, log in as root, then open <code>psql</code>:<pre><code class=language-shell>su - postgres -c psql
</code></pre><p>Congratulations! You are now running Postgres in your web browser.<p>Things to keep in mind:<ul><li>There is no internet access from inside the VM.<li>There is no data persistence, so changes are lost when leaving or refreshing the page.</ul> ]]></content:encoded>
<category><![CDATA[ Fun with SQL ]]></category>
<author><![CDATA[ Joey.Mezzacappa@crunchydata.com (Joey Mezzacappa) ]]></author>
<dc:creator><![CDATA[ Joey Mezzacappa ]]></dc:creator>
<guid isPermalink="false">270462b44374c1900301bdb1f6d9c8b050d7f4a97badd5db4ab40fe67fbde964</guid>
<pubDate>Wed, 24 Aug 2022 11:00:00 EDT</pubDate>
<dc:date>2022-08-24T15:00:00.000Z</dc:date>
<atom:updated>2022-08-24T15:00:00.000Z</atom:updated></item></channel></rss>