Everything you need to know about Appwrite Functions 0.13
Welcome to the Appwrite 0.13 Functions feature spotlight. Everyone at Appwrite is excited to see what you developers do with this new release!
We have a whole heap of updates to storage and functions including new storage adapters and large file support enabling the ability to stream larger files through Appwrite. This article will concentrate on the update to functions, but stay tuned for separate one that will talk about Storage.
First up is the main change that made all of the other changes possible, the new functions model! This new model is a complete rewrite of how we deal with functions, and if you want to learn more about the technical side of things, I heavily recommend reading our engineering blog post.
One breaking change, however, is the way you write your functions. Instead of writing a source file and executing it directly through the command line, we now import your file into Appwrite’s internal runtime server and execute a function you export. This means that you have to export your code as a function. This change will also come in handy with any communication handshakes, as the new execution model allows you to write global code that will only run once during the so-called cold start of a function.
The way this works is different from runtime to runtime, so we recommend that you checkout the updated functions documentation, however, I will show a small example with JavaScript.
Old function model was straight-forward, writing the code and logging the data on root level:
console.log(`Hello ${process.env.APPWRITE_FUNCTION_DATA}`);
The exact same code in new functions model will now be wrapper inside a function that is exported, and will use response object to return data:
module.exports = async (req, res) => {
res.send(`Hello ${req.payload}`);
}
As you can see, we are exporting an anonymous function as your source code’s main module export. This function will receive two objects: request and response. The types for these can be found within our functions documentation.
We then use the response.send function to return data instead of console.log, this makes it a lot clearer what exactly is being sent back.
Input is also much clearer now, instead of environment variable, you get the payload as part of request object. No more searching for environment variable name in the documentation!
The module.exports function will be executed every time your function gets an execution request, but code outside of it will be executed when the runtime initializes. This usually happens on first execution after a runtime gets put to sleep or after the build is finished.
🏄 Synchronous Functions
Yes! Functions can now be executed synchronously allowing you to easily build upon Appwrite’s functionality and introduce your own API endpoints to use along side Appwrite’s API. Simply pass the sync parameter to the create execution endpoint and your request will wait until the execution is finished. Once finished, a request will return the result of execution and time taken to finish.
For instance, if we used the same “Hello World!” example as before but this time added the “sync” parameter to the Create Execution endpoint we would receive the following as a result:
{
“status”:”completed”,
“response”: ”Hello World!”,
“time”: 0.0024
}
As you can see in the response, we get the status, output of the function and the time taken to execute the request. With a little bit of code in your frontend you can easily parse this result and even receive JSON from your function. You could even receive files if you encode them into base64 and decode them on the frontend.
This is just a fraction of what’s now possible with synchronous functions, so let your imagination run wild!
🚀 Speed Improvements
Another amazing benefit of the new functions model is that execution times have been significantly reduced compared to previous versions. In benchmarks we have seen a 98% reduction in warm start execution times, dropping averages from 0.1s to 0.015s! If you would like to see a deeper look into these benchmarks, make sure to checkout our engineering blog post.
📦 Automatic Dependency Management
With this functions update, we have added a new feature to Appwrite which allows runtimes to automatically install dependencies for functions. Appwrite can now detect a package.json
, composer.json
, pubspec.yaml
and many others to download and cache their dependencies ready for execution. This all takes place in the new build stage that just got added to functions.
The build stage starts right after you create a new deployment and will begin caching dependencies for non-compiled languages or building compiled runtimes. This new stage makes functions even faster as they don’t have to wait for dependencies on a cold start.
For some runtimes, certain steps must be taken so Appwrite can detect the dependencies. Please read up on this topic in the updated functions documentation.
👷 Compiled Runtimes
Compiled Runtimes? Yes, that’s right. Appwrite now has support for compiled runtimes such as Rust, Swift or Flutter. These new runtimes take longer to build, but are faster than their interpreted counterparts giving you even more options than ever to utilize any language you like for Appwrite. Rust and Swift do not currently support Automatic Dependency Management, however, support for it is coming at a later update.
🧑💻 CLI 2.0
Appwrite CLI 2.0 is here, bringing even more features than before! CLI 2.0 is now built with Node instead of PHP and does not require docker to install. This gives you more flexibility with how you use the CLI.
CLI 2.0 also introduces new features allowing you to build an entire Appwrite powered application without having to touch the console once. Packing everything into the the new appwrite.json
file allows you to easily move your entire project to a new Appwrite instance with just one deploy command.
We have also introduced function templates into CLI 2.0 so you can prototype and iterate on functions at speeds unparalled to previous versions!
Creating a new Appwrite project with a function is as simple as logging into Appwrite:
appwrite login
Then creating a new project:
appwrite init project
And finally creating a new function:
appwrite init function
This will create a new function with the template of the runtime you specified ready to be modified and deployed:
appwrite deploy function
As you can see, the CLI method of deploying functions has been greatly simplified and streamlined so you can deploy functions faster than ever!
🌅 Conclusion
We hope you enjoy these new updates to functions in Appwrite and we can not wait to see what you all get up to with them. If you have any feedback, questions or suggestions do not hesitate to join our Discord where most of the Appwrite community hangs out and are happy to help with any issues you may run in to!