Introducing pluggable PostgreSQL access for your wasmCloud apps
With wasmCloud, you can build applications out of WebAssembly components and pluggable, reusable capabilities, so you can focus on the core logic of your application and abstract away the rest, all using open source standards.
PostgreSQL is one of the most widely used relational database systems. If you want to use a database system like Postgres, wasmCloud makes it easy to simply plug in the functionality in a reusable, language-agnostic way, without wasting time writing boilerplate code.
In this post, we'll show you how to get started with the Postgres capability in wasmCloud.
Speed up development: Write queries without managing connection pools
Enterprise application teams need flexible database options, and for many, PostgreSQL is the tool of choice. But like many basic, non-functional requirements, teams can waste a lot of time getting to grips with libraries in this or that language and worrying about how to implement their database for a given project.
Capabilities abstract away database configuration and remove this toil.
In practice, every wasmCloud capability consists of two parts:
- An interface: The standard contract for a piece of functionality, defined in WebAssembly Interface Type (WIT), defining an API for any language that uses the interface.
- A capability provider: The executable that plugs in to wasmCloud and delivers the functionality in question.
In this case, you can use a single API for Postgres operations, regardless of your development language, and simply plug the Postgres capability provider into your application manifest when you deploy to wasmCloud. Because this isn't a one-size-fits-all SQL interface, it can take advantage of Postgres-specific features, like RETURNING *
and DDL in queries with explicit BEGIN/COMMIT
transactions.
Later on, if you need to migrate to another system, that's no problem—the wasmcloud-postgres
interface can be used by any system that supports the WIT standard.
Get started with Postgres on wasmCloud
Let's try it out. We'll use a Rust-based component, but you don't really have to be familiar with the language. For this example, you'll just need:
- The wasmcloud Shell (
wash
) CLI to build WebAssembly components and deploy to local wasmCloud. cargo
(part of the Rust toolchain) to help build from Rustdocker
to easily run an instance of Postgres.
Start Postgres and wasmCloud locally
First we need to get a Postgres cluster running. We can do this quickly and easily with Docker:
docker run \
--rm \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
--name pg \
postgres:16.2-alpine
In another terminal tab, we'll start our local wasmCloud, using the -d
/--detached
flag to run in the background:
wash up -d
We're running in detached mode to avoid opening another terminal tab, but if you'd like to check the logs, you can find them at ~/.wash/downloads/wasmcloud.log
.
Generate a new project
Now we'll generate a new project using the Rust-based sqldb-postgres-query
example from the wasmCloud monorepo as a template.
wash new component postgres-demo \
--git wasmcloud/wasmcloud \
--subfolder examples/rust/components/sqldb-postgres-query
cd postgres-demo
If you're familiar with Rust, in src/lib.rs
you'll see that the code for querying Postgres is very simple:
impl Guest for QueryRunner {
fn call() -> String {
if let Err(e) = query(CREATE_TABLE_QUERY, &[]) {
return format!("ERROR - failed to create table: {e}");
};
match query(
INSERT_QUERY,
&[PgValue::Text(format!("inserted example row!"))],
) {
Ok(rows) => format!("SUCCESS: inserted new row:\n{rows:#?}"),
Err(e) => format!("ERROR: failed to insert row: {e}"),
}
}
}
Next build your WebAssembly component from the Rust code.
wash build
The build process generates a folder called build
containing sqldb-postgres-query_s.wasm
.
Deploy the demo
The next step for a wasmCloud application deployment is usually to define the components and providers you'll be using in a deployment manifest.
For building locally, there is a prebuilt manifest (local.wadm.yaml
) in the project directory.
In the interest of security, we'll use the wash config
subcommand to define a "named configuration" called default-postgres
:
wash config put default-postgres \
POSTGRES_HOST=localhost \
POSTGRES_PORT=5432 \
POSTGRES_USERNAME=postgres \
POSTGRES_PASSWORD=postgres \
POSTGRES_DATABASE=postgres \
POSTGRES_TLS_REQUIRED=false
The Postgres provider knows to use this configuration because of our application maifest (local.wadm.yaml
), where we've referred to default-postgres
for named configuration.
Now it's time to deploy:
wash app deploy local.wadm.yaml
Confirm the application is deployed:
wash app list
You should see output like the following:
Name Deployed Version Status
rust-sqldb-postgres-query v0.1.0 Deployed
└ Demo WebAssembly component using the wasmCloud SQLDB Postgres provider via the wasmcloud:postgres WIT interface
Invoke the demo component
By default, the sqldb-postgres-query
component includes a simple invoke
interface, which enables using wash call
to trigger the component directly via the CLI:
wash call rust_sqldb_postgres_query-querier wasmcloud:examples/invoke.call
SUCCESS: inserted and manually retrieved new row:
[
[
ResultRowEntry {
column-name: "description",
value: PgValue::Text(
"inserted example row!",
),
},
],
]
Clean up
When you're finished, you can undeploy and delete the application:
wash app delete rust-sqldb-postgres-query
To stop your local wasmCloud:
wash down
Learn more and get involved
Explore the Capability Catalog to learn more about the first and third-party capabilities already available on wasmCloud.
Want to get involved with the community or learn more about building your own components and capabilities? Join us on the wasmCloud Slack!