DEV Community

Cover image for Serverless your way: Unleashing Appwrite Function’s true potential
Matej Bačo for Appwrite

Posted on • Edited on

Serverless your way: Unleashing Appwrite Function’s true potential

After countless months of research and never-ending feedback from our community, we are excited to announce that Appwrite Function received the biggest upgrade ever! Appwrite 1.4 introduces new Appwrite Functions that are truly unique and innovative, with a combination of features not found anywhere else. We achieved this by listening to real problems that developers are facing.

What problems, you might ask? One of the most common problems was using Functions as an endpoint, which was not really possible before. This was causing problems for incoming webhooks communication which is a common way to handle payments. Another regular issue was the customization of the build step, as private dependencies or TypeScript builds were not possible at all. Lastly, there were concerns about the speed of setting up a function and its environment variables.

Now let’s see how we overcame those barriers, and what new possibilities were unlocked.

About Appwrite functions

Appwrite Functions lets you extend Appwrite's capabilities by writing your own code that's deployed and managed by Appwrite. This means you can write your own custom backend solutions in Appwrite, without managing infrastructure. Build everything from custom REST endpoints, business logic, permission checks, or entirely new services on top of Appwrite. All with the ability to deploy from your GitHub repository, Appwrite Console, or through a custom CI/CD pipeline via our CLI.

We truly believe that every application is unique in its own way, and Appwrite Functions are a way to express that. We put extra effort into making sure Functions can do anything, but there is always room for improvement. Since Appwrite 1.3, we noticed a lot of community projects such as Appwrite Funcover or Appwrite Functions Proxy, and many GitHub feature requests like Global Environment Variables, Private Package in Functions, or Function with Typescript. All of that was a foundation for what we introduced in Appwrite 1.4.

Automatic deployments with GitHub

With any serverless functions, it’s important to simplify the deployment process. If you don’t, chances are that developers will prefer the good old way of managing a small Linux server. In Appwrite, we have support for manual upload in the Console, or using a terminal with a single command. We also have 0 downtime deployment support, to allow production apps to also take advantage of Functions.

With all of those cool features in place, we wanted to focus on empowering deployments. It becomes a nightmare for solo developers to manage a growing list of small functions that you have to redeploy, not to mention remembering which functions need to be deployed with specific changes you made. Our community also reported some unnecessary complexity when working on a Function in a team. The preferred way of deployment is using CLI, but there isn’t enough protection around who is allowed to deploy to production. That meant a longer onboarding process for teams to make sure developers were fully aware of how scary each command could be.

In Appwrite 1.4, we introduced a fully automated deployment using GitHub. You can now connect your GitHub repository to an Appwrite Function, and each change you push will trigger a deployment. You also get comments on your commits and pull requests, to inform you about the status of deployment. By configuring the production branch, you can decide which changes go directly into production. GitHub deployments also integrate well with your CI/CD, as Appwrite places checks on pull requests, to allow you to block merging changes that failed to build in Appwrite.

With GitHub deployment, your team is now protected from silly mistakes, and deployment is made even simpler. Alongside GitHub integration, we also added Function templates that let you get started with Functions within a few clicks!

HTTP functions and webhooks

Our mission has always been to meet developers exactly where they are in their comfort zone. By building Appwrite on top of your existing knowledge we ensure you can learn quickly and build fast.

When taking a deeper look into Functions, we noticed it wasn’t following those values. Some great examples are terms like Payload, Request variables, or Custom Data. They are easy to understand, but if we used terms like Request Body and Environment Variables, there would be nothing you would need to understand. Those would be common programming terms most of us already know, and there are numerous resources about them already written.

We also noticed Appwrite Functions had some limitations, as our community couldn’t find an easy way to integrate incoming webhooks with Appwrite. Incoming webhooks are a very common approach to integrating external services such as payment processing or chatbots. Due to that, our community made some tools such as Appwrite Funcover to overcome this problem.

Let me say a huge thank you to our community, which gave us the inspiration to redesign Appwrite Functions to follow HTTP standards.

In Appwrite 1.4, we assign unique domain to every function. You can use that, or add your own custom domain. Visiting this domain is yet another way of executing Appwrite Functions. Thanks to this small change, we are now able to provide much more information in the execution context such as request method, path, headers, or body. We can now also support many new response types such as image, PDF file, redirect, or rendered HTML. You could say that Appwrite 1.4 now lets you build your own mini web server as Appwrite Function, allowing you to do anything you could with a custom backend.

By following HTTP standards it’s now possible to handle payment processing, generate PDF invoices, run Discord or Slack bot, and even more. It’s now also possible to write a small HTTP framework inside the Appwrite Function and define your very own standalone service.

Global environment variables

With every Appwrite release, we introduce new services or improve existing ones. While it’s important to ship fast, we also focus on ensuring services work well together.

One of the most requested features since Appwrite 1.3 was an improvement to managing function environment variables. One common use-case for Appwrite Functions is to use Appwrite Server SDK and do administrative actions to documents, teams, or files. Since Appwrite doesn’t automatically provide an API key to every function (for security reasons), developers need to set it as an environment variable. This can get annoying very quickly, if you have to copy the same variables across dozens of functions you develop, not to mention there isn’t any easy way to do that either.

In the latest release, we overcame all of those problems with a few small features. Firstly, you can now set environment variables in project settings. Variables set here are provided for all the functions inside your project. No matter how many functions you have, you can now set the API key variable in one place, and get it distributed across all of them. We understand that customization of those might be necessary, which is why we decided to add automatic conflict resolution. If there is a variable defined in both project and function settings, the value from function settings takes precedence.

Secondly, in the Console, we designed a simple Variables Editor to let you edit all variables in a single action. This editor lets you import or export variables in ENV or JSON format, delete all variables, create them, copy, edit, read… All of which can be done in one text area without having to switch between modals.

Flexible build step

Customization is a must-have for any backend as a service. In the previous version, we wanted to find a good balance between customizability and simplicity. We tried to automatically detect what build step your function needs, but this check was simple and didn't account for custom build steps. We have seen our community face issues with TypeScript functions in Node, or issues with private dependencies in Python. We also noticed some CI/CD capabilities were missing for compiled languages, such as asset minification.

With Appwrite 1.4, we don't do any guessing anymore and rely on what you configure when creating a function or deployment. We still suggest reasonable defaults, but it's up to you to decide if that makes sense for your function, or not. As mentioned above, this allows custom commands such as tsc for TypeScript builds, private dependencies with token authorization export NPM_TOKEN="..."; npm install, or custom CI/CD tasks sh custom-build.sh.

You can now also keep a database or storage setup as part of your Appwrite Function. You can configure the build command to be npm install && node setup.js, and have the script to set up Appwrite Database and collection. You can see an example of that in our URL Shorter Template.

With the introduction of custom build commands, we decided to upgrade the build step even further and introduce real-time logs. You can now use build commands to minify, optimize, cache, test, and a lot more. Considering your build can now take minutes, we decided to improve the Console to show logs as they happen in real-time. This gives you much more info than the previous Building state with you sitting tight and hoping all goes well.

Closing notes

Appwrite Functions got the biggest upgrade in Appwrite 1.4, and are now capable of doing so much more.

We would love to hear your feedback! We invite you to join our Discord Server and share what you think about the new Appwrite Functions and 1.4 release in general. We are also here to chat, give support, and share memes.

Stay tuned for more information about Functions, as we will be publishing more in-depth technical article about how we built this technology, what challenges we faced, and how we managed to resolve them.

Top comments (1)

Collapse
 
williamcardoso profile image
William Cunha Cardoso

Amazing!