If you’ve recently tried to set up hosting for your web application, you might have noticed something. Hosting web applications in 2020 is both easier and harder than it was only a couple of years ago.
It’s easier because both the tooling and the hosting solutions have improved significantly. Tools like create-react-app, Next.js and, Gatsby have matured and there are tools introduced every day that help mitigate any shortcomings they have. Setting up hosting has also become much easier. Vercel (formerly known as Zeit) has gained a lot of support and popularity, while Firebase has continued its growth with the abundance of GCP (Google Cloud Platform) based services. Of course, Heroku, GCP App Engine, various serverless solutions, and others are still sticking around too. On top of that, we now have more services that cater to the needs of front-end developers, like Netlify. We’ve certainly come a long way from setting everything up from scratch on server instances.
However, it’s also harder to find hosting these days because of the number of options available. As mentioned in the previous paragraph, there are easily a dozen options, which each have different benefits and caveats. Each has different ways to incorporate them into your project as well. That’s not to mention the difference in pricing models.
In this article, I’ll compare Firebase and Vercel, based on my recent experiences using them to host Next.js projects. (Note: This article was not sponsored by either of the companies behind these products).
Comparing the Technology
Firebase offers two solutions that you can select based on your needs. Its hosting solution is basically Google Cloud Storage (GCS) with some additional tooling. This is useful for static websites such as an exported Next.js website. GCS has been fulfilling tech companies’ needs for years. Combined with Google’s Cloud CDN, it performs well and is reasonably priced if your files are not very large.
The second solution Firebase offers is Firebase Functions, which caters to more dynamic web applications. Firebase Functions is built on GCP’s Cloud Functions with additional tooling to bind it with other Firebase features. You can clearly see a pattern here. Firebase’s method of adding a new feature is using what is available in GCP and merging it with the other Firebase features. In my opinion, it’s a good strategy to reuse technologies that are already stable and focus on their usability instead. It also allows Firebase to keep adding features at a fast pace.
Cloud Functions has been around for years now. I’ve been following it for a long time and have seen significant improvement in its documentation as well as its tooling. It’s serverless so it comes with the usual advantages of being scalable and cost-effective. However, it also comes with the negative side of serverless technology: It has cold starts. This means that if the function is not used for a certain amount of time (it can be ten minutes or one minute), Google will scale it down to 0. This causes a boot up when a new request reaches this function. This boot-up is known as a cold start. If your function is getting a fair amount of requests, say a few requests per minute, this should not be an issue for you. But if you’re just starting out, it might give you a headache or two. Now, there are many strategies to improve this cold start period — some are common sense, some are more like workarounds. In my experience, reducing the cold start time is not an easy fight. Various workarounds are possible, but they’re just that, workarounds. It’s all part of the extra effort you need to expend to compensate for the shortcomings of serverless technology!
Another issue with Cloud Functions is its support for Node.js. For some reason, Google Cloud Functions only support ancient versions of Node.js. At the time of writing, Cloud Functions officially support only Node.js version 8, which is not supported by the OpenJS foundation anymore — not even for security updates. Cloud Functions also supports Node.js version 10 as beta. This indicates that this support is not stable. Mind you, the OpenJS Foundation (the foundation behind Node.js) put version 10 in the maintenance phase — only important updates will be available. What I’m trying to say is that Cloud Functions are several years behind in terms of technology.
The last important thing to mention about Firebase Functions is that, if you’re using it as a Next.js backend or something similar, you will need both Firebase Hosting and Firebase Functions to properly proxy your website. You’ll need to configure something called a rewrite to redirect your Firebase domain to your Firebase Function. This operation is easy to implement but comes with a critical tradeoff. It’s only supported in the us-central1 region. So you will need to set your Firebase Function in a US region. If your target audience is not in the US, expect some serious performance cost.
Vercel’s (aka Zeit) technology has been under development for several years now. It is built on top of AWS Lambdas so it’s also serverless. You’ll experience the same benefits and shortcomings of serverless technology. However, there are a few key differences.
AWS Lambdas have better Node.js support. This allows Vercel to up its support as well. It officially supports version 12, which is the latest LTS (long term support) version of Node.js. Vercel also effortlessly supports multiple regions, so that’s one less thing to worry about.
It’s only fair to point out that Vercel is only usable for hosting. It lacks many of the features Firebase has. The most notable ones are the database and the cloud storage, both of which are critical for any modern web application. This is not a deal-breaker, however. It’s possible to make use of Firebase’s database and storage while using Vercel’s hosting. There will be a performance cost since the database requests will be leaving the AWS datacentre and going all the way to Google’s datacentre, so this is not ideal. Database requests should not leave the local network.
One major advantage of Vercel is its focus on Next.js-like frontend applications. Its CI (Continous Integration) pipeline, features, and optimizations revolve around them. Vercel’s deployments are quite fast and they take effect quickly. It also lets you easily deploy multiple versions of your app, allowing you to deploy feature branches under different subdomains. There are also some magic optimizations applied by Vercel, but I’ll get to them in the performance section.
This section is the most important part for me. I was willing to look past many differences — after all, there are often many ways of compensating for various disadvantages — but there is no way to compensate for a bad performance.
The most notable performance items for Firebase were:
- Cold starts.
- Having to use the US region for Firebase Functions.
- Various optimizations that need to be implemented manually.
The most notable performance items for Vercel were:
- Cold starts.
- Vercel Edge Network (CDN).
- Automatic optimizations on Next.js projects.
Let’s start by comparing the cold starts.
Below are two performance reports I generated using web.dev for the same codebase. I’ve made sure that they’re not used for a certain amount of time and that they’re tested with cold starts.
I ran the same tests again soon afterward to compare the warmed-up versions.
In both these graphs, it’s clearly visible that Vercel performs better than Firebase Functions in their default settings. There are a couple of reasons for this difference. For instance, Vercel separates a Next.js project into multiple AWS Lambdas based on the pages of the project. This decreases the amount of code to be loaded for each request; which makes the cold starts shorter, as well as reducing the overhead of each response payload.
Another reason Vercel is faster is because of its smart CDN that caches static resources and serves all the requests from a closer datacentre to the user. You can, of course, configure the same functionality on Firebase, making use of Google’s many CDNs and datacentres. However, it’s available out of the box, which means you’ll have to do more DevOps work.
Vercel’s cache times can also be configured using the Cache-Control header. It’s possible to configure it based on the request path. If you're interested in its implementation, check out their documentation here.
Another important item for me was, of course, the regions they support. I’m based in Germany so a hosting that is only available in the US was far from ideal.
Comparing Ease of Use
Firebase’s local development tooling has improved significantly over the years. As a developer who used Firebase in the past, I was pleasantly surprised by how much more integrated its features are. It’s also impressive that they have emulators of various features for local development. It’s not perfect but it’s enough for testing your app in a production-like environment. It still took me some time to set everything up to get it working. You need to read various documentations to make them all play nicely with each other. However, it’s possible to do most of your Firebase related operations using Firebase’s and GCP’s command-line tools.
One feature that’s missing from Firebase is continuous integration — that’s still something you need to figure out for yourself, at least for now. Once you get the CI sorted, it’s quite simple to make it work with Firebase. You only need to generate a token and you can perform many operations on CI. I’ve used Gitlab’s CI for my project and I can’t complain!
Vercel’s CLI is also quite useful. People at Vercel do their best to keep everything as simple as running the now command in your terminal. The initial setup is quite simple and is done with the same now command. They also let you link your project to whichever Git service you're using. When linked, Vercel triggers deployments automatically in its own CI whenever you push to the master branch. Of course, this operation is configurable too — it also allows users to specify the build command they want, which allows us to insert extra commands into the build process. For example, you can insert an npm test to ensure that the changes are tested before they’re deployed.
Vercel’s local development tooling is relatively young and still in beta. It does work but it’s not as comprehensive as what Firebase offers. Here’s Vercel’s short documentation for vercel dev.
Firebase has a pretty detailed pricing model. Estimating the cost of Firebase is about as easy as doing your taxes. It does have a generous free tier, but going above the free tier gets complicated quickly. Hosting, storage, databases, and various other features are all charged separately, with each having multiple variables. It would be easier for you to check it out for yourself.
Vercel used to have a similar pricing model since it is also based on cloud technologies. They recently simplified it a lot though, as described in their recent blog post. It seems that they chose Github’s pricing strategy — they now support hobbyists for free forever and focus on charging companies instead.
My subjective conclusion from experimenting with these technologies has resulted in me using Firebase’s Storage and Database combined with Vercel’s hosting.
I was tempted to use Firebase Functions because I would be dealing with only one service and only a single set of tools. That is indeed what I did for a while. Unfortunately, I was eventually disappointed with the performance of Firebase Functions. Cold starts became a burden when I was presenting my project to third parties and the various workarounds to improve the performance became time-consuming.
I had used Vercel before, but it wasn’t a recent experience. So I decided to give it another go and see how they compare. I ended up using Vercel as the back end and Firebase as a database and storage.
I recommend you try them both and decide for yourself. I hope my notes here will save you some time.
Let me know what you think and how your experience has been with these technologies.