Two weeks ago we announced SurrealDB 3.0, along with a new feature called Surrealism that lets you write your own functions in Rust that can then be annotated to call directly from the database.
In this blog post, we are going to take a look at what use cases Surrealism solves and easy it is to get started with it. Let's begin by taking a look at how functions are used in SurrealQL and how Surrealism expands their range of use.
Functions in SurrealDB
SurrealDB has always had user-defined functions that look like this:
These functions can get to any complexity and length that you like.
The next type of function was added in SurrealDB 2.0: closures. Closures are anonymous functions that can work in read operations that can access both arguments and parameters in their scope.
However, both defined functions and closures live inside the SurrealQL query language inside the database.
Surrealism surpasses this limitation by letting you define functions in Rust instead, with all of the available bells and whistles that you get from the Cargo package manager and crates.io ecosystem.
These functions are then compiled to a WASM binary that then can be linked to from the database itself.
Being able to add functions just like that means that new functionality can be added today, to your existing SurrealDB version, with the only setup being two DEFINE statements - one to set up a file bucket, and one more to show the database where inside this bucket the WASM file is located.
Why we made Surrealism
Making Surrealism was in fact an absolute necessity for a project like SurrealDB in which the community plays such a large part. That's because a lot of requests are for features that are nice to have, but don't quite make sense to merge into the code for the database itself. But with an extension system, you can make the feature yourself!
Using Surrealism is basically like installing apps on your phone. You can't modify the OS of the phone itself, but you can install a new app any time you find one that appeals to you. Similarly, you can build and upload an app for other people to try out.
Some examples
Let's look at two case studies where Surrealism allows a functionality to be added that was not possible before.
Case 1: A well-intended PR
Sometimes you will see a well-intended PR that isn't able to be accepted, such as this one. That PR used Rust's fake crate to create a number of database functions that could be used to seed a database with mock data: fake names, addresses, companies, and so on. The function signatures would have looked like this.
While useful (and tempting), it would lead to an increase in the binary size for a functionality that is not core to a database, so it was not able to be merged.
Case 2: A feature request
Another example comes in the form of feature requests, such as this one from a user who would like to see Serbian added to the list of languages that could use the Snowball filter.
First let's look at what the Snowball filter is and what it does. This filter is used inside a DEFINE ANALYZER statement to enable full-text search. The filter uses something called stemming which reduces words to something like a root form. This is best seen through an example. In the two queries below we have defined an analyzer that first splits a string by class (whitespace, dots, numbers vs. letters, etc.) and then passes it through the Snowball filter for English.
The output shows some words like 'absolut' and 'necess', which are the shortest possible forms that can be used to match on a word. Note that this isn't an exact science as you could argue that 'make' should be 'mak' in order to match on forms like 'making'. But that is a subject for another time.
Now, the interesting part about this feature request is that Serbian is one of the languages with a Snowball stemmer. So adding Serbian is technically doable, except that it would require quite a bit of work.
The reason why is that the crate that SurrealDB uses to implement it hasn't been updated for a while. There was even a PR to add Serbian to it but it was never merged and has since been closed. So adding Serbian to the list of languages would require something like the following:
Try contacting the crate author to bring up the issue again
Wait a while, fork the repo if there is no response
Contacting the author of the PR to add Serbian to see if it's okay to use that PR, or implement it ourself
Follow up with a PR to the SurrealDB source code
Now, if you'd like to put a PR together that accomplishes all that then feel free!
However, thanks to Surrealism, this sort of problem can be resolved today.
Making a Surrealism module
So let's put a Surrealism module together that allows you to create mock data as well as work with Serbian text. This section is a somewhat quicker walkthrough of the same steps as this page in the documentation, so check that page out too to see more details.
There is a bit of boilerplate to start.
The boilerplate
First we need to add a line in Cargo.toml to create a dynamic library that can be loaded from another language.
And then a surrealism.toml file is needed. We can just copy and paste this into the file.
Annotating functions
Now we can make some functions and annotate them.
The code for the fake data couldn't be simpler, as the fake crate uses a dedicated function for each type of fake data. You do have to choose a language though. Let's go with German for the fun of it.
To make a function a Surrealism function, just add the #[surrealism] annotation to the top. This will allow them to be exposed in the binary once the code is compiled.
Calling these functions will generate an output something like this.
Now let's move on to Serbian. Implementing Snowball ourselves would be a lot of code, so let's go with something simpler for demonstration: stop words. Stop words is a method by which you remove all the most frequent words from a language that are not very useful when working with text. For English these are words like the, a, an, but, at, on, is, and so on.
Rust has a stop words crate which doesn't have Serbian, but does have Croatian (language code hr). Both Serbian and Croatian are one of the standards of Serbo-Croatian which means that a tool for one works pretty well for another.
This crate has an example of the tool in action here.
Now we have a small hiccup here: unlike Croatian, Serbian is also written using the Cyrillic alphabet. However, a quick search through crates.io shows that there is a crate to convert Serbian Cyrillic to Latin and the other way around.
Combining these two, we can create a function called serbian_stop() that converts the input to Latin or Cyrillic. Instead of exposing that, we'll make two more functions, serbian_stop_latin() and serbian_stop_cyrillic(), which will get the #[surrealism] annotation so that they can be called directly from the database.
Putting all the functions together gives us this code.
Compiling and accessing the Surrealism module
With the functions done, it's now time to compile the Surrealism module. That can be done with the surreal module build command. Follow this with --out and the file name, which must have the extension .surli.
You should see the following output.
Now it's time to start the database with surreal start. It needs two environment variables to make this happen: one to allow the files and surrealism experimental features to be used, and another that shows the location of the .surli file that we just compiled.
Now we'll connect to the database either via Surrealist or the following CLI command.
Once we are connected we just need two more statements: one to define a bucket for the files, and another to define a module, a module being a collection of Surrealism functions.
And that's all you need to do! Let's call the first three functions to see what output we get. It'll be different every time, but will look something like this.
Now let's try the Serbian functions. We'll choose this passage from the Serbian Wikipedia:
Неолитско насеље у Винчи удаљено је око 14 km од ушћа Саве у Дунав, што је изузетно повољно место које је омогућило да постане фокална тачка простора југоисточне Европе.
That passage is about a pre-historic neolithic culture that existed in and well beyond present day Serbia. It means:
"The Neolithic settlement in Vinča is about 14 km from the confluence of the Sava and the Danube, which is an extremely favorable place that allowed it to become a focal point of the area of Southeastern Europe."
We'll take the Cyrillic form and see if we can turn it into Latin and vice versa.
Success! Even if you don't know the language, you can compare the input and output to see that the output does indeed lack a number of words. This is clear when you line them up against each other.
So there we have it. In the space of a 350-line blog post we've managed to turn SurrealDB from regular SurrealDB 3.0 into one with a few extra "apps" that let you create mock data on the fly, or work with a new language that wasn't available before.
And since a Surrealism plugin is a WASM binary written in Rust, you can compile it yourself or share it for others to use. The ability to share what you've built is what makes a plugin system like this so extensible.
Community example
To finish up this post, let's quickly check out an example of Surrealism in action. SurrealDB user (and ambassador!) Horváth Bálint is the author of an app called recet that he described as follows:
Recet is an open source, work in progress recipe manager application built using Nuxt and SurrealDB. It is motivated from personal needs and the curiosity to see how much functionality can be squeezed out from using SurrealDB as the backend. My goal is to create a web app that feels great on both desktop and mobile using modern technologies like PWA, View Transition API, all while showcasing many features of SurrealDB.
One of the features of this app is a Surrealism function! Let's take a look at it. As you can see, it uses a crate called html2text. Here's part of it.
Then we have the same DEFINE BUCKET and DEFINE MODULE statements as above:
And then a query via the JavaScript SDK that calls the function.
As you can see, it's the same process described in the first examples above. Annotate the function, compile the module, use DEFINE twice to connect to it, and the function(s) are yours to call.
The final app, by the way, looks like this. Personally I think the kókusztejes gombás fehérbab looks particularly good, or the póréhagymás mascarponés gnocchi with the leeks replaced with grated cheese.

Back to you
There's no telling what the SurrealDB community will do with Surrealism now that 3.0 is here and the word is getting out.
We can't wait to see what you build!
Get started with Surrealism
Go to the Surrealism Docs to get started. We are excited to see what extensions you build, be sure to share them in our Discord channel.
Thank you for being on this journey with us!
