PL/Rust 1.0 and its trusted language mode
In E62 of “5mins of Postgres” we talk about PL/Rust, its 1.0 release and how it implements trusted language support in Postgres.
Let's jump in!
PL/Rust, for those of you who are not familiar, is a way to use Rust to create your user defined functions in Postgres. Similarly to how you could use PL/pgSQL or PL/v8 to run custom code in Postgres as part of your application, you can now also do this with Rust code.
Earlier this week, version 1.0 was released by the PL/Rust team. I think this was a tremendous amount of effort. The team behind PL/Rust has previously created pgx, which lets you create shared library type extensions in Postgres. PL/Rust, on the other hand, is for creating user defined functions that let you extend your application logic on the database side by using Rust.
PL/Rust has a few trade-offs to think about, and a lot of them come from the fact that you are using Rust. Rust has to be compiled, that compilation can be slow sometimes. The very first time you're creating a function will be slow, but then when you're executing it, it's going to be a lot faster.
The team behind PL/Rust claim this it is 10 times faster than PL/pgSQL. If you have really complex database side logic, this might give you a huge performance benefit. Obviously, you get other benefits from Rust, such as
- that you have type definitions
- you can analyze all your code at compile time
- you will have better error handling
- and more.
When PL/Rust was released, there was actually quite a good discussion on Reddit where they talked about some of the trade-offs. And one of the challenges right now is that it is a bit challenging to get running. It's not just the Postgres extension that provides PL/Rust that you need to install, but it actually uses a custom Rust standard library behind the scenes, as well as a custom Rust compiler driver.
Now, this is early, but Yurii from the Omnigres project started testing out PL/Rust. This was a very long day for Yurii. But one of the things he learned here is that PL/Rust does take quite some space to compile initially. It does take about 8 gigabytes just to get all the dependencies in place, and then you also need to have a good amount of RAM, roughly 16 gigabytes of RAM, to build PL/Rust initially. This might make it a bit frustrating if you were including it in your build environment. Also, first time function compilation, as mentioned earlier, does take quite a long time.
But I'm sure that the team behind PL/Rust will spend time optimizing these things and so I think we'll see a lot more improvements over the next months and years.
Now, one thing that I found interesting is the claim that it is a trusted language. If you're not familiar with the definition of trusted, "TRUSTED" means that you give permission to any user in the database to create a user defined function with that language. Somebody could just go in and create a PL/Rust function.
As the Postgres documentation notes, the "TRUSTED" flag should only be given to languages that do not allow access to the database server internals or the file system. That last part is really important, because the big risk here is that you have a Postgres user, for example just a regular application user, escalate their privileges through means of a user defined function.
In a standard Postgres install, PL/pgSQL, amongst a few other things, are considered trusted. Untrusted, for example, would be PL/Python. Which is why you see Amazon RDS not supporting PL/Python, but they are supporting PL/pgSQL.
PL/Rust considers itself trusted. In order to do that they've actually disabled quite a few features to preserve that security:
- You can't use unsafe in your Rust code.
- You have restrictions on which crates to use.
- And they're also restricting a few other things.
If you have specific Rust crates you want to use, you have to explicitly allow those. You're guaranteeing that PL/Rust can consider those safe. You actually do have to vet these crates and make sure that they don't let you escape into the operating system level.
What I think is really impressive is what the PL/Rust team has done with the standard library in Rust. They essentially reworked the Rust standard library, developing a version of the Rust standard library that lets you write standard Rust code, but behind the scenes it either calls into Postgres functions or errors out, and through that lets you make sure that the Rust code that uses the standard library doesn't escape to the operating system level.
All in all, you can see that there was a lot of work put into PL/Rust. Congratulations to the team to releasing the 1.0 version today. I look forward to seeing more of PL/Rust in the future!