With Angular now widely adopted across both web and enterprise companies, the question of which backend to pair with it becomes increasingly relevant for new projects.

This post examines why the latest Firebase could have an impact on web development comparable to Angular's own rise, and why combining the two might represent one of the most significant advancements the field has seen in years.

Despite all the technological progress made so far, building web applications remains far more complex than it ideally should be — though a tool like Firebase could help close that gap.

Which backend should I choose?

Imagine you're kicking off a brand-new application, with Angular already locked in as your frontend framework. An excellent choice, to be sure!

From there, you'd likely start constructing the backend with the tech stack you're most comfortable with, typically a REST API that shuttles data to and from Postgresql, MySql, another preferred SQL database, or possibly Mongo.

Your selection would probably fall into one of these categories:

  • Ruby developers are strongly likely to opt for Rails
  • Python developers may lean toward Django
  • Node developers might choose the MEAN stack, pick Hapi over Express, dive into Websockets with Socket.io, or try Meteor. Using a SQL Database? Sequelize is a solid option!
  • Enterprise Java developers often put together a Spring/Hibernate setup with Spring Boot and Spring Data, potentially adding Spring REST if Spring MVC alone isn't enough
  • Those in the C# / .Net space typically rely on the .NET framework with the Entity Framework, among other choices

It's natural to fall back on the go-to solution you've relied on for years and build a custom REST API in the usual fashion — and that approach certainly works.

However, I'd encourage you to pause and weigh an alternative that could dramatically improve your efficiency as a Web Developer.

And if REST is still your preference, we've got some exciting news for you as well!

What is included in this post

The focus here will be on Firebase, AngularFire, and building applications with the Angular / Firebase stack. Here's the list of topics we'll tackle:

  • Most Applications need a solution for the same problems
  • Why Backendless development does not exist in practice
  • Why use JSON Data Stores for Web Development
  • WebSockets and the Application Service Layer
  • The Firebase SDK, how to use it with Typescript
  • Firebase Keys, References, and Snapshots
  • Data Modeling in Firebase - The Right and the Wrong Way
  • The AngularFire Library - Querying a List
  • Querying Objects in AngularFire
  • Modifying Lists and Objects in AngularFire
  • Firebase Authentication
  • Firebase Built-In REST Functionality
  • What is the FIREStack Architecture?
  • Building batch Jobs using Firebase Queue
  • Firebase Storage and HTTP/2
  • What Firebase does not include yet
  • Summary

Several sections include linked video tutorials for those who prefer watching over reading. Let's jump right in!

Most Applications need a solution for the same problems

When designing an application, we often convince ourselves that its features are so distinctive that they demand a highly tailored, custom design. In practice, that's seldom true: the vast majority of applications are essentially moving data in and out of a database using a handful of standard modification patterns and search filters.

This generalization doesn't always hold across the entire app — frequently, there are screens that are straightforward CRUD interfaces, while another portion might be as specialized as a Gmail-style inbox for handling message exchanges.

A missed opportunity to build apps faster

The blend of common, repetitive data manipulation tasks alongside unique, app-specific functionality offers both a prime chance for optimization and a likely drain on productivity:

Far too often, we construct an entirely bespoke backend when sizable chunks of it could be operational straight out of the box. The need for some custom pieces leads us to build the whole thing from scratch.

Backendless development does not exist in practice

The concept of backendless development, along with the entire BaaS movement, could paradoxically have set back the wider adoption of Backend as a Service as a practical choice in application development.

The idea that your entire backend could be plug-and-play is appealing but, as we know, rarely accurate. Our chat app definitely can't be considered backend-free.

A backend of some kind is almost always necessary

Basic CRUD and a host of standard queries function without a custom backend. Nevertheless, there will always be tasks like a scheduled job that scrubs messages for banned words, which aren't handled out of the box.

Faced with this, we could skip a BaaS altogether and build a bespoke solution, constructing dozens of REST controllers by hand for even routine update operations. That's a path ripe for repetition, mistakes, and burnout.

BaaS isn't an all-or-nothing deal

Choosing a BaaS doesn't lock you into building everything with it. A single custom subsystem doesn't force a fully custom architecture.

Imagine delivering 90% of the system using ready-made infrastructure while reserving our limited time and focus for the remaining custom 10%—often the actual core of the product.

Firebase enables this approach and, as we'll see, it also simplifies the custom backend portion considerably

The REST to Relational Impedance Mismatch

For those of us developing single-page apps that call RESTful JSON endpoints, data feels naturally JSON-like. But plenty of backends rely on non-JavaScript tech and relational databases underneath.

That's where productivity suffers. We constantly shuttle data between formats that are nowhere near JSON, and mapping becomes a daily burden.

Even routine updates feel heavy due to the ORMs and mapping layers involved. Consider this JSON structure on the frontend:

If changing the lesson title were as easy as mutating the object and calling db.save(modifiedObject)—or anything close—wouldn't that be ideal?

The reality is usually a much messier chain:

  • fire off a REST Ajax PUT or PATCH request
  • handle it server-side, possibly translating into an object via a tool like AutoMapper in C# or Java
  • nod is an exception here since mapping hardly comes up
  • persist it with an ORM to a relational table, or an ODM if it's going to a document store

What about JSON Data Stores?

That's far too much work for a simple JSON save. A direct JSON data store is the real answer—and that's essentially what the Firebase Real-Time database is.

It brings real-time features and respectable performance to the table, but those extras aren't its main selling point.

What makes Firebase worth it

At its core, the Firebase Database shines as an exceptionally straightforward JSON data store. That's the feature that lets us build web apps at a faster pace.

Some folks think of it as only for chat rooms or real-time games. In practice, it's a general-purpose database, and it began as a fork of MongoDB.

Your existing SQL data modeling instincts aren't useless here—most of what you know transfers over—we'll dive into that shortly.

Why JSON Data Stores fit Web Development

JSON data stores do away with most of the mapping mess we just described. Below is what a typical data console might show for one such database:

Firebase database courses

We’ll come back to that odd "KT-etc." key in a moment.

Imagine the Firebase database as one massive JSON object floating up in the cloud — essentially a single, huge object.

Now, glance at the object’s top level: you’ll see nodes called Courses and Lessons. These names look a lot like SQL table names, right?

Data Modeling in Firebase

Prefer video content? Check out this brief clip on Firebase data modeling:

This clip comes from a broader YouTube Playlist — the full list of Angular and Firebase videos is available there.

Our focus here is demonstrating how straightforward data modeling can be in Firebase, using a One to Many relationship as the example.

Consider this a brief primer; the core takeaway is that Firebase's data modeling approach is far closer to the SQL mindset than you'd expect. For additional data modeling patterns, check out this post.

In this scenario, the model consists of:

  • a set of courses
  • a set of lessons
  • a course containing multiple lessons
  • a lesson assigned to exactly one course

That's the classic one-to-many setup. Now, how do we represent this in Firebase? The right approach varies, but generally there's a sound option and a problematic one.

Starting with what's typically the bad approach

Suppose each course gets a lessons property holding an array of lesson objects:

It looks reasonable on the surface, but we've likely just introduced a performance bottleneck.

Where might this backfire?

Occasionally, though, this pattern is exactly right. If a course is meaningless without its lessons in your app—if there's no use case for fetching a course alone—then nesting lessons inside is sensible, since you'll always pull them together.

But that's rarely the case. Usually you need course data without dragging along every lesson.

In Firebase, Reading Means Pulling Everything

In Firebase, when a course is queried, the entire node comes back—lessons included. There's no way to grab just the course fields and ignore the lessons array; whatever sits inside the fetched node is returned in full.

Sometimes that's acceptable. Yet picture a course holding 500 lessons, where you only want the title and length for a course overview. Even with real-time capabilities, that model would swiftly choke the database once a handful of users hit it.

How do we typically handle this in SQL?

With a relational database, the steps are:

  • split courses and lessons into distinct relational tables
  • query only the courses table when all you need is the title
  • combine the tables to retrieve lessons for a specific course
  • connect lessons to their course using a foreign key

And that's the same strategy we'd apply in Firebase. Those SQL principles translate directly—only the vocabulary shifts here and there, but the logic stays intact.

Structuring a One To Many Relationship in Firebase

The initial move is to remove lesson data from the course node entirely. You could leave just a list of lesson keys there, but with large courses that's 500 entries cluttering the node.

Let's instead strip lessons out completely and place them in a separate root-level node—the Firebase equivalent of a relational table, which is the closest we can get:

Firebase database courses

We'll come back to those keys shortly, and they possess some really neat traits! It's now evident that the lessons node constitutes a list holding a set of IDs, each corresponding to a unique lesson identifier. Expanding the ID property reveals the lesson content as well as a courseId.

This attribute bears a striking resemblance to a foreign key in a SQL database. Yet a foreign key goes further—it acts as a declarative rule ensuring data integrity, a capability Firebase offers through its Security Rules, which, despite the terminology, serve purposes beyond conventional security.

Given that Security Rules deserve their own dedicated discussion, let's zero in on the data modeling here. So, how do we establish the connection between a course and its lessons?

Establishing an association node in Firebase

To connect the data, one approach is to introduce a lessonsPerCourse node into our database:

Firebase database lessons Per Course

For each course, we add an entry under that node, using the course key as the identifier. Then we attach a list to that property, containing the lesson keys. In JSON, every object property requires a corresponding value.

Here, though, our goal is purely to establish a connection between a course and a lesson, making the value unnecessary. As a standard practice, we assign the value "true" in such cases.

If the course-lesson relationship were to carry its own attributes—for instance, a start and end date for the association—those attributes would be stored as the value of this node, replacing the "true" placeholder.

Model cautiously, denormalize if needed

The association approach outlined above is likely the optimal choice in most scenarios. Generally, keeping your data as flat as possible is advisable, but alternative structures might occasionally be required.

This mirrors the situation with SQL databases: the fully normalized data model isn't always the right fit, so denormalization becomes necessary.

When uncertain about data modeling in Firebase, our recommendation is to lean toward flatness. However, denormalization is a common practice in Firebase—don't hesitate to create multiple screen-specific views of the same data and maintain their consistency using multi-path updates.

Our advice is to always maintain a fully normalized version of the data in your database, adding extra denormalized views of that same data when the need arises.

Other modeling concepts, such as many-to-many relationships, could be described in similar fashion and would feel quite familiar. But at this point, one question might be nagging you: what exactly are those unusual-looking keys?

Are they truly necessary? Could we instead rely on integer sequential numbers?

Firebase Keys

I strongly recommend adopting Firebase keys from the outset—avoid trying to circumvent them, as they will spare you considerable frustration:

  • These keys are built to function in a distributed environment
  • They can be generated synchronously on the client, even when offline

Is all just random characters?

Not at all. The key's initial segment embeds a timestamp accurate to the millisecond, while the latter segment holds a random number. Although it's technically feasible to extract that timestamp from the key, it's wiser to refrain from doing so—if you need the timestamp, store it separately as an object property instead.

Consequently, when these keys serve as the keys for your lists, the lists will be naturally sorted by timestamp down to the millisecond. Beyond that precision level, within each millisecond, the keys are arranged randomly, not following the order of generation.

We'll observe these keys in action in the sections ahead; for now, you're likely curious about this:

How do I query the data, how do I modify it What about Joins, how do I join the data back?

We'll address these questions shortly, but first, it's important to note that direct SQL like queries are currently unavailable in Firebase.

For robust search functionality, it's advisable at this time to implement a dedicated search solution, as outlined here. The Firebase API is evolving continuously and may introduce additional search features later, yet nothing substitutes for this type of Google-style full-text search.

Nonetheless, the Firebase SDK provides substantial querying capabilities without requiring you to master a separate query language.

The Firebase SDK, how to use it with Typescript

To read from and write to the Firebase Real Time Database, several approaches are available:

  • work solely with the Firebase SDK as a Javascript library
  • pair the Firebase SDK with Typescript
  • leverage AngularFire, which also provides access to the Firebase SDK

Let's begin by setting up all of these components, since we might employ each one at some stage:

npm install firebase angularfire2 @types/firebase

The Firebase DB is really just one big object

To make it clear that the Firebase database is essentially one massive JSON object stored remotely, we will fetch the entire database at once and log it to the console:

This action will output the full database to the console, which is something you should avoid in practice! Typically, you will want to target a specific sub-node, such as a course or a lesson.

However, there is something deeper happening in this example:

Whenever any change occurs in the database, an entirely fresh value of the entire database is pushed back to the browser and displayed in the console.

The callback we supply, which takes a snapshot member variable and logs it, will be triggered on every database modification. This interaction is facilitated through server push, a mechanism we will explore later on.

Another side effect also took place:

you have now stored a full copy of the database locally in the browser!

All data pulled through the Firebase SDK is stored in a cache layer, so when you run the same query again, the information comes straight from the client-side cache instead of the server.

Firebase References and Snapshots

In its API, the Firebase SDK relies on a few core concepts, two of which we just encountered: References and Snapshots.

For a deeper dive into these topics, check out this video covering some of the Firebase SDK Fundamentals:

Now let's break down what occurred when the database delivered the fresh value, and how that actually operates. Were we relying on a long polling Ajax request?

WebSockets and Their Advantages

When the browser supports it, the Firebase SDK client establishes communication with the Firebase Real Time Database over a Websocket; if that support is absent, the SDK automatically and seamlessly switches to Ajax long polling.

This entire mechanism remains hidden within the Firebase SDK, meaning you never write Websocket code yourself when working with Firebase.

Why are Websockets faster?

Websockets rely on a persistent TCP/IP connection, so data exchange avoids repeatedly paying the overhead of establishing a TCP/IP session—something that happens with every Ajax Request.

Additionally, using a websocket to transmit an object only incurs the cost of the payload itself, skipping the usual HTTP headers that the browser attaches to a standard Ajax request. These headers can dwarf the actual data, particularly for small payloads.

If your goal is transmitting just a counter, those extra headers might inflate the transferred payload hundreds of times beyond what you'd expect.

Data Joins in Firebase

Given the speed of the websocket connection between the SDK client and the database, performing data joins on the client side is practical for the volume of data typically shown in a UI, and even for notably larger sets.

Firebase provides no server-side support for join queries, so you must fetch each necessary path via separate requests:

  • retrieve the course from courses, then extract its ID
  • pull the lesson IDs for that course from lessonsPerCourse
  • fetch each lesson from lessons using its corresponding ID

If this becomes problematic at larger scales, you can build a data "view" by creating a node that holds a course's lessons data. This likely won't be necessary if you paginate the data.

This approach mirrors SQL database strategies: when a query becomes too heavy, run it in advance and save the outcome to a reporting table. That table is simpler to query and gives a sustained aggregated snapshot of more detailed data.

A Summary of What the Firebase SDK includes

In brief, the Firebase SDK bundles all essentials to work with the Firebase real-time database (authentication is discussed next):

  • a callback-based API for "subscribing" to database segments
  • client-side caching
  • server-side push via websocket-based transport
  • Ajax fallback when necessary
  • support for database transactions, i.e., atomic multi-path updates

The Real Time database and Observables

The concept of subscribing to database segments fits beautifully with RxJS Observables, which model this pattern exceedingly well. Promises fall short for a real-time database since they return just one value, while we need an async primitive capable of managing multiple values over time.

This is exactly where the AngularFire Library enters the picture—including AngularFire in your app also brings in the Firebase SDK directly, a point we'll touch on shortly.

The AngularFire Library

Let's begin by integrating AngularFire into our application:

npm install angularfire2 --save 

Next, we set up AngularFire inside the application module:

Once this minimal setup is in place, every AngularFire injectable becomes accessible throughout the whole app. As an example, we can inject the main Firebase SDK instance and work with it directly:

This mirrors the earlier example — it pulls down the entire database, which you should avoid in practice. Still, it serves as a decent introductory exercise if you're new to the topic.

Suppose you'd rather fetch just the course list or a single lesson instead of the full database. Here's how that would look:

However, take note: we're still working with a callback-based approach here, not an Observables-driven one. That's because, in this case, we're leveraging the Firebase SDK's native API.

AngularFire enhances this by offering two Observable binding methods, letting you subscribe to any segment of the Firebase database:

  • You can subscribe to an entire collection
  • Alternatively, you can subscribe to one specific object

Let's now explore the AngularFire Observable API in practice, and see how well it complements the Realtime Database on the client side.

Interacting with the Real Time Database through AngularFire

Imagine we want to subscribe to the course list to get notified when a new course appears. Earlier, we saw how to accomplish this with the Firebase SDK directly; now, let's switch to AngularFire:

Here, we've injected the AngularFireDatabase injectable — this is the service responsible for communicating with the real-time database.

Now, let's see it in action; you may also inject the AngularFire service as demonstrated in this clip:

Querying a List in AngularFire

How can we read lessons from the AngularFire database? The database object provides two core methods for retrieving data: list and object.

In the findAllLessons() service implementation shown earlier, the list method is used to fetch the complete lessons child node, located directly underneath the Firebase root node.

What does the list call return? You get an RxJs Observable, and each emission represents the current contents of that lessons array:

  • the initial emission reflects the list's state at the time of subscription
  • with no modifications to any lesson, there will be no subsequent emission
  • when a lesson gets modified, a fresh value arrives, bringing the entire updated array

Here's what matters most about the Observable from AngularFire: it won't emit a completion event after the initial value (even though applying first() would change that). This puts it in contrast to the Observables used by the Angular HTTP library.

This Observable stays active throughout its lifecycle — it fails to complete — meaning you receive new emissions over time. That is precisely the essence of Observable behavior.

The list method supports a query configuration object, enabling features such as pagination, ordering by a specific property, and filters.

Querying Objects in AngularFire

In a similar manner to querying a collection, you can target a single entity with the object method as well.

The result of such a call is an Observable that emits, each time something changes, a fresh snapshot of the object with the ID you requested.

These two primary AngularFire APIs handle large parts of the real-time data tree as Observables with minimal effort. Yet AngularFire also lets you write data.

Modifying Lists and Objects in AngularFire

Assume you have a collection called courses$, where the trailing dollar sign is a naming convention that tells developers it's an Observable. Its emissions give you the list of all courses.

To append a new course to that array, you'd use something like this:

Observe that invoking push returns no Observable. Instead, you receive a promise-like object, so you can still chain a call to then() if you need to react to the operation's outcome.

AngularFire includes these write capabilities, yet they form a deliberate, narrower set compared to the full SDK. Using the SDK app directly by injecting it into your services while also leaning on AngularFire is perfectly acceptable, giving you access to every feature the SDK offers.

However, don't conclude that the Firebase SDK is mandatory when working with the Realtime Database!

That's worth emphasizing: you may skip the SDK entirely, and here's why.

Firebase and REST

If caching data on the client through the Firebase library doesn't appeal to you, or real-time behavior isn't demanded, plain Ajax calls will do just fine. Any REST client gets you there without the SDK.

Everything stored in Firebase is addressable through a URL, which always begins at your database's root URL. That single endpoint handles all data access and manipulation:

  • GET fetches every value within the targeted node
  • PUT overwrites all pre-existing data with what you supply
  • PATCH allows partial updates to designated properties
  • DELETE removes data at that location
  • POST inserts a new entry into the list

So you built your backend data layer without creating any custom REST routes. There's one minor detail: you must append .json to the URL.

For instance, suppose the root URL of your database happens to be:

https://final-project-recording.firebaseio.com

So you’re looking to pull every course stored beneath the top-level courses node. Sending a GET request to the URL below will return the full set of courses as JSON:

https://final-project-recording.firebaseio.com/courses.json

And this is the data you get as a result:

All this REST functionality comes ready to use without needing to write any code whatsoever!

That said, the SDK is usually a better choice: it comes with built-in caching and supports atomic multi-path updates, in contrast with the REST API.

Yet, for straightforward CRUD operations, the REST API works well and is remarkably handy.

Building Custom Backends and Batch Jobs

Way back in this POST, we noted that while Firebase likely eliminates much of the need for backend code, there would always be parts that remained custom anyway.

So what's the approach for creating a custom backend with Firebase?

Several options exist. For handling UI actions that need custom backend logic, one approach is to leverage the real-time database as a messaging layer between the browser client and your server.

Here, a client writes a message to a queue, and the server publishes its reply back into a response queue. At first glance, this seems like it would be sluggish — but if both parties rely on Websockets, it turns out to be quite fast for the typical volume of actions a human generates through a UI.

This pattern goes by the name FIREstack Architecture, and you can dive deeper with this great video as well as this blog post from @ChrisEsplin.

Going this route spares you from standing up an HTTPS service or purchasing pricey certificates, especially if you're a small outfit — and it keeps the overall setup far simpler.

What about Batch jobs?

Picture a UI action kicking off a batch job. You could have that action write a processing request to a queue, which a separate Node process then consumes and turns into a response.

Tools like firebase-queue make this possible, so let's install it and walk through a quick example:

npm install firebase-queue --save

What is the approach for writing to a queue from the user interface? Consider a scenario where you need to delete a lesson from a course. This isn't a straightforward data removal, but rather a logical deletion that involves intricate business rules.

Take a situation where users who already purchased a course and viewed the lesson before its deletion should still have access to it. Only newly enrolled users should be blocked from seeing it.

Your first move on the frontend is to submit a deletion request to a queue:

This action sends a deletion request to the queue. To handle that request, you set up a node process that is lightweight and doesn't need to accept any inbound HTTP or HTTPS traffic.

Setting Up a Firebase Queue Consumer Node Process

This process leverages the same Firebase SDK, which is universal or isomorphic Javascript, functioning equally well in client and server environments. You also have the option to employ Firebase queue to handle the queue request and build a consumer:

When you define your consumer, the callback provides several arguments to manage the queue request:

  • data provides the information stored in the queue request, which is currently in a 'PENDING' state
  • invoke progress() with a number to indicate the task's completion percentage
  • for successful task completion, you must call resolve(), which deletes the task from the queue
  • reject() is necessary when a business error surfaces during the task; this flags the task as errored, making it eligible for later retries, which you can adjust in firebase-queue
  • should a technical error occur, such as a thrown exception, the task gets marked as errored in the queue, with the error message available within it

Benefits of crafting custom backends in this manner

This approach shows that we can construct custom backends with considerably less effort compared to spinning up HTTP or HTTPS processes in node and managing incoming requests. Instead, we write these straightforward, non-network-reachable processes, which simplifies security, and rely on the identical Firebase SDK used on the frontend, allowing us to reuse existing knowledge and conserve mental energy.

We avoid needing deep expertise in a separate ecosystem or language; it remains plain Javascript, with the added advantage of Typescript support. Additionally, the Firebase SDK extends beyond Javascript to numerous other languages.

Beyond the real-time database, what other offerings does Firebase provide?

Firebase Authentication

Firebase goes well beyond the Real Time Database. Among its many capabilities is native user authentication, whether via email and password or through external providers such as Github.

Authentication is the sort of logic best avoided building ourselves: it is simultaneously very easy to botch and mission-critical, and its functionality is identical across every application.

How many Users and Roles SQL database tables have you encountered in your past projects? It's a feature that can function entirely out of the box from day one using a BaaS solution, yet we frequently rewrite it from the ground up in every project.

Sample of applying Firebase Authentication

With either the Firebase SDK or AngularFire, authentication can be activated with just a couple of API calls. Suppose we want to authenticate a user using email and password; here's how it's done with the Firebase SDK:

Authentication is just one of the many issues Firebase can address for us without custom code. Other features essential for building an application include Cloud Messaging, Hosting, Storage, a Test Lab, Crash Reporting, and more.

Firebase Storage, Hosting, and HTTP/2

For a single-page application, assuming you aren't using bundle splitting, your frontend typically boils down to just 3 static files:

  • the index.html, which serves as the lone HTML page of your app, generally sparse in content
  • the CSS bundle
  • the Javascript bundle

That's the whole thing—only 3 static files! An often-overlooked benefit of single-page apps is how straightforward production deployment becomes: a handful of static files, upload them to Amazon S3 or your nginx or apache server, and you're finished! At least for the frontend side.

Why not upload those files straight to Firebase's servers to avoid a separate DNS lookup for fetching them elsewhere? An SSL certificate is automatically provisioned, ensuring robust security with no extra configuration.

On top of that, with Firebase Hosting you get complete HTTP 2 support, and you should also host all your images there too. This way, your index.html, CSS and JS bundles, along with your images, all come over a single TCP/IP connection and one DNS request, giving you that edge in performance.

Even if HTTP 2 isn’t available, Firebase Hosting remains a highly practical option, just like the rest of Firebase — uploading files through the command line is straightforward. Check out this Firecast on Hosting to see it in action.

Summary

Here’s a quick recap of why Firebase could make a significant difference in web development today:

  • it offers a JSON database straight out of the box, which helps bridge the gap we often face with SQL databases
  • for Angular developers, AngularFire provides a seamless way to work with Firebase
  • building custom backends is simpler with Firebase Queue and the Firebase SDK, which behaves identically on both client and server
  • it handles several challenges we’d otherwise need to code from scratch each time, such as authentication
  • it delivers a full stack CRUD solution for the CRUD sections of our application
  • much of the knowledge from building other systems still carries over

In my view, Firebase is simply a better way to build web apps: it’s straightforward to reason about, performs well, and offers a top-notch developer experience. It lets us zero in on our application, ship it to users faster, and cuts out a huge amount of work, making it a genuine pleasure to use.

Thanks for reading! Be sure to browse the list below for more Angular posts and resources.

Sign up for our newsletter to get notified when new posts like this are released:

If you’re eager to dive deeper into Firebase’s advanced features and the Firestore database, take a look at the Serverless Angular with Firebase & AngularFire Course — it covers Firestore, Firebase Authentication, Firebase Storage, and Firebase Cloud Functions in great depth.

New to Angular and just starting out? Check out the Angular for Beginners Course:

Angular, Firebase and AngularFire Crash Course - Why Firebase ? — figure 4

Did you like this post? Then you might want to check out these other well-read articles as well: