Introduction
Serverless technologies have become the de facto way for developing cloud applications in many companies, especially in the startup world. On AWS, these services range from database providers like DynamoDB, file storage solutions like S3, and computing services like Lambda and Fargate.
This article focuses on computing services and how to choose a language suitable for your situation, when developing applications with either AWS Lambda or Fargate.
Familiarity first
Building a serverless application can have its quirks, as you are developing for a very specific platform with very specific constraints. However, at the end of the day, you are still building a software product, and your team's strengths should be one of the most important factors when making this decision.
Whether a language like Rust can improve the performance of your application or reduce your monthly bill by using less computing time is irelevant if your team cannot write good Rust code. If you don't have developers that are proficient in one of those better-performing languages, your development cost will very much exceed your cloud computing time savings. In addition to that, there are global payment services written in Ruby and large scale games with backends written in Python out there - your language choice will not kill your product.
Technically speaking, it's possible to use any language for developing such applications. You can deploy Docker images to both Lambda and Fargate, so you can build applications written in any language you prefer. However, there's more to it.
Given that you are developing on AWS, you will want to make use of the services they offer. And while all of them provide APIs that let you interact with them, having an official SDK to work with can go a long way. Since AWS distributes SDKs for the most popular languages, this will most likely not be an issue for your team.
Another important aspect to take into consideration is your current codebase. If you are building a project from scratch, you can disregard this, but if you are just building new serverless features for an existing project, chances are you can share some of the code you already have. This will increase your development speed, as well as prevent synchronization errors between the 2 codebases (e.g., having different specifications for the same database entities).
Available options
This section looks into some of the more popular or interesting choices for developing serverless applications. We will not look into all of them (as they include Ruby, Swift, and PHP), but will base the list on a few criteria: AWS support, popularity and available resources, and general usability.
Python and JavaScript (Node)
Python and JavaScript share a few similarities, which result in the same pros/cons when it comes to their viability for serverless development.
Firstly, they have good AWS support, with SDKs being available for both of them, as well as Lambda runtimes. It's also possible to use the CDK and write your infrastructure in either language.
Secondly, you have to look at the languages' features. They are both interpreted languages, which results in decent cold starts, but slower runtime performance than compiled languages. They are also dynamically-typed, which can lead to faster development time, but can also make your applications more error-prone. Working with JSON structures is also extremely easy in both languages, which makes them particularly good for Lambda functions.
Both JavaScript and Python are popular languages with large ecosystems and numerous libraries. (although, you would have to deal with NPM if you choose JavaScript)
In the end, both languages are solid choices, especially if you already have a codebase written in one of them, or if the industry you are working in tends to favor one of them (e.g., Python in the Machine Learning field).
.NET (C#/F#/PowerShell) and JVM (Java/Scala/Kotlin)
These are grouped because, again, they share many similarities and philosophies.
The main focus from an AWS support seems to be the primary language of each platform (C#/Java), but there's also an official Kotlin SDK. Lambda specifically offers runtime for C#/PowerShell and Java, but in the end, any language that compiles to either platform can be deployed to a Lambda function.
Both .NET and JVM used to suffer from higher cold starts on Lambda, but we now have solutions for this problem with AOT compilation (.NET Native AOT / Java GraalVM Native). So in the end, you are getting better cold starts AND higher runtime performance than interpreted languages like Python and JavaScript.
The popularity of these platforms does not even need to be discussed, as they are amongst the most used technologies (even though that might be less true in the startup ecosystem).
However, the syntax for both C# and Java can get quite cumbersome, especially when working with Lambda requests/responses or having to deal with other Amazon services interactions. This is the same reason why, even though both languages benefit from CDK support, it's not a good idea to write your infrastructure in one of them - the CDK heavily relies on structures such as nested lists and dictionaries, which can get unmanageable pretty quickly in such languages.
To conclude, both .NET and JVM languages can be great choices, especially if you are expecting high workloads for your application. Just note that this might come at the cost of slightly larger development times.
Go and Rust
In the case of Go and Rust, they do share some similarities, but also seem to be polar opposites in some regards.
While maybe less popular than the afore-mentioned languages (with Rust even more so), both languages do get significant AWS support, with SDKs are available for both Go and Rust. The Lambda runtime for Go is deprecated, and an official one does not exist for Rust, but the community is offering great development and deployment tooling for them.
They are both known for being great in terms of performance, being compiled languages, which is an important point if you are expecting high workloads. And, although they do it in different ways, both focus on the correctness of the code, which will save you from future headaches in production.
The significant difference between them is in terms of simplicity. While Go is known for its plainness and understandability, Rust can give even the better programmers a hard time in the beginning.
Go might be, hands down, the best option you have for serverless development (in the absence of other factors). Rust remains a solid option, but only if your team is more than comfortable with it.
Other options
Your choice is not limited to the languages that have been mentioned here. AWS offers SDKs for other languages such as PHP, Ruby, Swift, and C++, and even a Lambda runtime for Ruby. (Ok, Ruby does seem to check all the marks for being a solid choice, it just doesn't get a separate section in this article.)
When choosing a language that might lack in one of the aspects (especially AWS support and general popularity), make sure there is good reasoning for it. There usually isn't, and you might end up shooting yourself in the foot.
Conclusion
The most important idea to take away is that there is no one-size-fits-all language that you can use to seamlessly fix all your problems. You should first consider how familiar and comfortable your team is with different technologies, as well as how well-suited those technologies are for achieving your specific goal.
Comments