NOTE about this article
Since this is related to our business application, I do not write all the things happened to our project in detail and some backgrounds are manipulated. However, I believe that the tech-related parts are all the fact and I tried to write as precisely as possible. I hope this article will help you gain some knowledge and solve your problem with the serverless shift.
This article was copied from my personal blog and not plagiarized from some other place.
Why we used Typescript instead of Java on Serverless from Junks, GC cannot sweep
Introduction
Serverless is one of the most modern and highlighted software architecture and recently more and more developers are starting to using it in their own application or services.
I also am loving it a lot now and I cannot think of getting back to the self-managed server model anymore.
Basically, if your application is well designed for scaling and distributing, most of the feature we rely on the server application has been lost, I believe.
So these days, I always encourage serverless if asked about the architecture or designs of web service.
Btw, since it is a totally different approach from the traditional development method, Serverless requires us to refresh our knowledge and review the tech stacks we've been using.
What language we should use also is one of the things we need to review.
Finally, we started to use *Typescript and have been working with it for more than 1 and a half years.
And, as just a personal opinion impression though, it was much nicer than we expected it to be.
So I would like to write what was a problem with the old tech stack and what was good after switching it to Typescript.
Why we needed to give up Java
Before talking about the reason for choosing the Typescript. I would like to explain the reason why we gave up the previous tech stacks with one of the most excellent languages, Java.
--------------
NOTE
In the first place, I'm an enthusiastic Java Lover and my Mother Tongue also in Java. (Java 4 or 5, when there was no generics feature.)
I have studied about the JVM and was inspired a lot from it as well. I guess it was made by god.
So here I do not mean to despise or insult Java at all.
Any comments or complaints about Java are not welcomed, just it didn't work well with serverless at the moment.
---------------
Ok, sorry, let's go ahead.
We’ve been using Java as the primary language for our service for a long time and we actually know that Java has a lot of advantages like
- Platform-Free
- Well designed JIT compile
- Excellent GC
- Well-structured grammar
- Type strong
- Supports functional programming recently
- Having a lot of libraries
- Trustable communities.(Not Oracle, but developers community)
and etc..
We really appreciated it and rely on them a lot.
However, when we tested our code with serverless, we found that Java is not too good to be running on the FaaS service such as AWS Lambda.
The reasons are the following.
- The overhead to launch the JVM is not ignorable.
- Moreover, our primary framework Spring took more time for launching containers.
- The final package of source code is relatively large. (Sometimes more than 100MB)
- Hard to proxy the requests without using web framework when the number of functions increased
- G1GC or JIT compile not works well since the container stops very shortly
- Can not enjoy the benefit of the platform free since it always running on EC2 with Amazon Linux image. (Not cons, but just reduced the reason to use Java)
All the problems listed above were so annoying, but here I wanna explain the most troublesome one of the above.
Cold Start of Lambda is too troublesome
The most troublesome thing we faced at first was the overhead of the cold start. Yeah, I guess most of the serverless developers may have faced the same issue.
We used AWS Lambda for computing and AWS Lambda launches the container every time a request comes from users.
Once it is launched, it reuses the same container instance for a while, but in the initial launch, it needs to launch the Java Runtime environment and all the necessary web container or environments of frameworks.
Additionally, one container can be used to handle just a single request and cannot be used for multiple requests concurrently even though your application is ready with hundreds of request threads in your thread pool. It means that when several users send the request to the endpoint at the same time, AWS Lambda needs to launch another Lambda container to handle the other requests.
It was so troublesome actually since normally we cannot estimate the number of concurrent requests and hot standby mechanism doesn't work. (even if we make it somehow.) Eventually, it will force users to wait for several seconds to open the page or process the request and we were sure that it will surely degrade the user experience.
After seeing how the cold start is annoying, though we’ve already had a lot of codes written in the past several years, finally, we gave them up all and switched to use another language.
Why we chose Typescript
Actually, it is a bit shameful though, we’ve decided to use the Typescript from a really early phase without deep thought or comparison with other languages.
However, honestly, we have no choice of using other languages supported by Lambda from the beginning other than Typescript under that circumstance.
At first, we have no choice to use dynamic typing languages. The service and code are supposed to be running, supported, maintained and extended for a long time by variously skilled developers. So we would not like to use the dynamic typing languages for serverside.
Thus, Python and Ruby were out of options.
C# and Go have a totally different character from the language we (and other teams) were working on and it may take some time for other newbies to catch up.
Of course, we all were aware that these days those 2 languages, especially Golang is winning the share gradually thanks to its nature.
However, the arch change was a too immediate mission and we didn’t have much time to catch it up for ourselves as well. Thus, though those 2 languages were fascinating for us, we gave up using those langs.
Benefits of using the Typescript
So finally, we have decided to use Typescript.
The benefits of Typescript are as the following.
- Type Strong
- Much small size package
- Super fast launch overhead
- Able to reuse the knowledge of javascript and Java
- Node libraries and communities are awesome
- Suitable for functional programming even compared with the javascript
- Able to write well-structured codes with Class and interface
As everybody knows, static typing is quite an important factor for the long-running project like B2B so I do not write much about it here. Here I wanna explain how the Typescript worked well with. With other features of the typescript, the type really works well more than we expected.
Less overhead to launch with small packages
Probably this is the most important factor to switch from java to Typescript in serverless. (Other benefits are almost about the benefit of using the Typescript itself)
As mentioned in the previous part, Java has overhead to launch the JVM and DI/Web container for the framework.
Additionally, as the nature of Java, it has the following weak point to be used in the AWS Lambda.
Typescript doesn't have those weak points and it resolved our concerns.
Multithreading and its eco-system
Multithreading is a powerful functionality of Java and it really helps us implement the high-performance codes.
Even the JVM itself is using it for the garbage collections to provide great performing runtime.
(See G1GC or JIT Compile)
However, you will find it takes from 100s milliseconds to several seconds to prepare for all the thread used in the container.
It is small enough and ignorable for the ordinal architecture like client-server running on EC2, but totally not ignorable for serverless applications which is running on the FaaS like Lambda.
Typescript is based on the nodejs and it only supports single thread by default. (Async or Sync is just controlled by call stack, not by thread)
Thus, the time to launch it is much short than Java with modern frameworks.
Big Package Archive
In serverless, normally, a small-sized package is preferred.
When the lambda container is launched, the container downloads the source code from the AWS managed source bucket in S3.
Time to download the S3 is normally small, but not ignorable if it is 100MB or 200MB.
With nodejs, the code size of a package could be relatively small compared with Java.
Honestly, I am not too sure why it is even now, but probably for the following reasons. (Please teach me in a comment if you know more.)
- Java frameworks are usually comprehensive and can contain a lot of dependent libraries to cover everything, but javascript framework or libraries are more like on-the-spot and doesn't contain unnecessary files so much.
- Javascript can write multiple modules or functions in one file and can maintain it with less effort, but Java requires to design the classes and interfaces with multiple files to write maintainable and well-structured code.
Actually, when using Java, the packaged jar was nearly 200MB at the biggest.
However, with using the nodejs, it could be reduced to 35MB+ at last.
It was partly because we tried to reuse the Spring Tech stack in the previous arch.
However, even after removing the unnecessary dependency and optimization, a package for one function still required 50MB.
Able to use the knowledge and eco-system of javascript
As we have been working on the web service, we have some kinda stacks of knowledge about javascript and nodejs.
Through the era of Jquery to the modern javascript like React or Vue, we’ve already learned the pros and cons of it and have obtained some know-how to write good code in javascript.
Typescript is a kinda extensive language of javascript and will be transpiled into javascript at last.
Therefore, many of the idiom or grammar is extended from the javascript and we could easily start to write the code without many preparations.
Additionally, most of the useful libraries are providing its type definition for the typescript so that we were able to enjoy the benefit of nodejs eco-system as well.
Works well with the functional programming paradigm
Functional programming is quite an important paradigm when we are talking about the tech trend these days.
It will let you write simple, testable, less-dangerous and stable codes with its nature.
AWS Lambda always requires us to get rid of the state from our code. Functional programming is requiring us to isolate the side effect or state from the functions and this idea surely is making our codes for Lambda more maintainable.
Basically, as John Resig told in Secrets of the JavaScript Ninja, javascript is supporting functional programming from the beginning.
It treats the Function as the first-class object and jquery also were supposed to be written in a functional way as well.
However, plain javascript is a dynamic typing and it sometimes introduces some difficulties to write good functions.
The variety of functions we can express with a single primitive type is quite limited and using the Object type for the arguments/return value is sometimes troublesome.
With typescript, we can specify the type of arguments or return value.
Additionally, following functionalities lets you write the code more safe, simple and expressive.
- Type: Lets you distinguish the common type and its aspects such as string and UserId or Promise and Either.
- Interface/Class: Lets you organize the sets of the arguments/return type as suitable for the context in the service.
- Enum: No explanation necessary I guess.
- Readonly: Lets you make your objects immutable.
- Generics: Lets your functional interfaces be more expressive.
Typescript has more advantages for the functional programming, but do not mention them here all. (Partly because it's the advantage of javascript rather than Typescript..)
Please try it and enjoy your discoveries.
Able to reuse the best practice we used in Java
Once you see the tutorial of the typescript, you would find it is quite similar to the Java or Scala.
We’ve been trained how to write good code in Java through our long journey with them to some extent.
We were aware of how we should design the classes and interfaces, how to use enum efficiently, how to make the stream API maintainable in Java and it was not the thing we can throw away instantly.
Thanks to the similarity of Typescript and Java, we could easily take the previous practices over to the new codebase.
Typescript supports the interfaces, classes, access modifier, and readonly properties(equivalent to the final of property in Java) and It actually helped us a lot to reuse the best practices we learned in Java including Object-oriented programming practices and the Design Patterns. (FP and OOP are not antinomy and can be used in the same project, I believe. )
If we would have chosen Python or Ruby, probably we needed to struggle again to find how to apply the practices into the new language for a long time,
(Actually, of course, I know it’s a lot of fun, but not for the time in hurry arch change)
Of course, we didn’t do the copy-paste of the logics in the existing java classes.
However, even though we re-wrote them with 80% from scratch, it didn’t take much time to write it again with acceptable quality.
Conclusion
We are still new in the journey of Typescript and needing a lot to learn, but already found a lot of benefits of it and we really are enjoying it.
If asked now, probably using the Golang can be an option, using the Micronauts with GraalVM also can be an option or maybe there can be more options we can choose. However, I am really satisfied with the typescript so far and believe it is one of the best options we can choose in serverless.
Of course, already have faced some difficulties with Typescript and serverless like how to do the batch processing with relatively slow language, how to do the concurrent computing or distributed processing, how to make the workflow, how to overcome the timeout of API Gateway or how to ensure the data consistencies.
However, all those things are the most interesting things for us, geeks, to resolve.
Actually, we already have found some practices and have overcome them. I will write it in the near future.
If you are struggling with Java on serverless and losing hope for serverless, I strongly suggest you consider Typescript. I can promise that it will work better than you expect it to be.
Thanks for reading through this long article. I am happy to receive your comment or contact if any.
Top comments (1)
Are there any metrics to provide concrete evidence to show it? Like how much of an impact does it really make?
I really like Java for it's ecosystem, but I love serverless even more.