These days, you don’t need to know how to set up servers and databases from scratch to build full-stack applications. The advent of serverless technology makes it easier to scale your applications without the hassle of manually managing the infrastructure. In the modern technological world, everything is driven by apis.

There are many tools that can help you build scalable applications without the complexity and operating costs typically associated with full-stack development. Choosing the most appropriate solution for your project can save you a lot of hassle and technical debt down the road.

In this guide, we’ll compare Firebase and Fauna, evaluating each tool’s learning curve, complexity, scalability, performance, and price.

What is Firebase?

Firebase is a background as a Service (BaaS) tool that provides a variety of services, including authentication, real-time database, Crashlytics, storage, and serverless cloud capabilities, to name a few.

  • Real-time databases and cloud firewalls are used to store file structured data and synchronize applications
  • The cloud feature is a serverless feature for deploying custom business logic
  • Firebase hosts enable you to deploy both static and dynamic content
  • Cloud storage is designed to store and provide a large amount of user-generated content, such as photos and videos.

What’s a Fauna?

Fauna (formerly FaunaDB) is a serverless application framework that provides a GraphQL API layer on top of traditional databases. In addition, it turns the DBMS into a data API that provides all the functionality you need to manipulate the database.

Fauna.

  • Multiple models to manipulate data
  • Multiple apis for data access, including native GraphQL
  • Strong data consistency
  • Built-in certification

To demonstrate the pros and cons of using Firebase and Fauna, we’ll walk you through how to build an example with each database.

Here’s a quick demo we’ll build.

React and Firebase

On the front end, React and Firebase are common because they allow front end developers to build full-stack applications. Firebase is a BaaS tool that makes it easier for Web and mobile developers to implement common functions such as authentication, file storage, and CRUD database operations.

For a more in-depth look at Firebase configuration and initial setup, see “Getting Started with React-Redux-Firebase.”

Firebase component diagram

Let’s start with the entity/relationship diagram and component diagram.

First, create firebase.js in the root directory and add the following code.

import firebase from "firebase";
const config = {
  apiKey: "API_KEY",
  authDomain: "AUTH_DOMAIN",
  databaseURL: "DATABASE_URL",
  projectId: "PROJECT_ID",
  storageBucket: "STORAGE_BUCKET",
  messagingSenderId: "MESSAGING_SENDER_ID",
  appId: "APP ID",
};
// Initialize Firebase
firebase.initializeApp(config);
export default firebase;

Copy the code

Once you’ve configured Firebase, you can use it directly in your components.

Read data from Firebase

Next, we’ll get all the project data from Firebase.

useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      const db = firebase.firestore();
      const data = await db.collection("projects").get();
      setProjects(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
      setLoading(false);
    };
    fetchData();
  }, []);

Copy the code

Use the following code to connect to Firebase.

  const db = firebase.firestore();

Copy the code

Once Firebase establishes a DB connection, we can retrieve data from a specific collection using the following code.

const data = await db.collection("projects").get();

Copy the code

Write data to Firebase

Inserting data into Firebase is as easy as reading it. First, create a project.

Add the following code to the onClick (https://blog.logrocket.com/a-guide-to-react-onclick-event-handlers-d411943b14dd/) function.

const db = firebase.firestore(); db.collection("projects") .add({ name }) .then(async (res) => { // component logic comes here // setModalState(! modalState); toast.success("Project created Successfully"); }) .catch((err) => { toast.error("Oops!! Something went wrong"); console.log("err", err); });Copy the code

We can use Firebase’s Add function to add data to the specified collection.

Update data in Firebase

To update data in Firebase, use the set function.

 const db = firebase.firestore();
    db.collection("projects")
      .doc(id)
      .set(
        {
          description: project.description,
        },
        { merge: true }
      )
      .then((res) => {
        toast.success("Project Updated Successfully");
      })
      .catch((err) => {
        toast.error("Oops!! Something went wrong");
        console.log("Error while updating project", err);
      });

Copy the code

The Merge option allows us to add new data along with existing data. Otherwise, it will replace the data.

Firebase ACID transactions

Firebase supports transactions. You can use batch setup operations to keep data consistent. For example, if you delete an item, you also need to delete all tasks associated with it. Therefore, you need to execute it as a transaction.

There are a few important things to note about transactions.

  • Read operations must precede write operations
  • If a concurrent edit affects the document read by the transaction, the function calling the transaction (the transaction function) may be run more than once
  • Transaction functions should not directly modify the state of the application
  • The transaction will fail when the client is offline.
var sfDocRef = db.collection("projects").doc(); return db.runTransaction((transaction) => { // This code may get re-run multiple times if there are conflicts. return transaction.get(sfDocRef).then((sfDoc) => { if (! sfDoc.exists) { throw "Document does not exist!" ; } // delete tasks here }); }).then(() => { console.log("Transaction successfully committed!" ); }).catch((error) => { console.log("Transaction failed: ", error); });Copy the code

The setting of Fauna

Before we can start setting up Fauna for our sample application, we have to create an account, database, and collection in the Dashboard.

Now it’s time to set up a Fauna. We will structure our application as follows.

  • config
  • components
  • api

Config will set Fauna and the API will contain all queries to the DB. Create db.js and add the following.

import Fauna from "Fauna";
const client = new Fauna.Client({
  secret: process.env.REACT_APP_Fauna_KEY,
});
const q = Fauna.query;
export { client, q };

Copy the code

Create data in Fauna

Next, we will create apis for read, insert, and update operations.

import { client, q } from ".. /config/db"; const createProject = (name) => client .query( q.Create(q.Collection("projects"), { data: { name, }, }) ) .then((ret) => ret) .catch((err) => console.error(err)); export default createProject;Copy the code

Each query in Fauna starts with client.query. To insert data into DB, use Q.crew to wrap collections and data.

q.Create(<Collection>, {<data>})

Copy the code

Read data from Fauna

There are two ways to read data from Fauna.

  • Use indexes to retrieve all data
  • Get the data directly from the collection, whenever you have itid

When you need to retrieve all data rather than specific data, it is recommended to use indexes to retrieve data.

import { client, q } from ".. /config/db"; const getAllProjects = client .query(q.Paginate(q.Match(q.Ref("indexes/all_projects")))) .then((response) => { console.log("response", response); const notesRefs = response.data; const getAllProjectsDataQuery = notesRefs.map((ref) => { return q.Get(ref); }); // query the refs return client.query(getAllProjectsDataQuery).then((data) => data); }) .catch((error) => console.warn("error", error.message)); export default getAllProjects;Copy the code

Here, we use the index of the collection to get all the project data. By default, we can use q.paginate paging data and get all indexes/ ALL_projects compliant data.

If we have an ID, we can get the data as follows.

client.query(
  q.Get(q.Ref(q.Collection('projects'), <id>))
)
.then((ret) => console.log(ret))

Copy the code

A one-to-many relationship among Fauna

Relationships are an important concept when designing databases and their schemas. Here, we have a project and task entity with a one-to-many relationship. There are two ways to design our database for this relationship: you can add the task ids as an array to the project collection, or you can add the project ids to the data for each task.

Here’s how to add the task ids as an array to the project collection.

Here’s how to add the project ID to the data for each task.

Let’s follow the first approach and add the task ID to the project collection.

import { client, q } from "../config/db";
const createTask = async (projectId, name, description) => {
  try {
    const taskData = await client.query(
      q.Create(q.Collection("tasks"), {
        data: {
          name,
          description,
          projectId,
        },
      })
    );
    let res = await client.query(
      q.Let(
        {
          projectRef: q.Ref(q.Collection("projects"), projectId),
          projectDoc: q.Get(q.Var("projectRef")),
          array: q.Select(["data", "tasks"], q.Var("projectDoc"), []),
        },
        q.Update(q.Var("projectRef"), {
          data: {
            tasks: q.Append(
              [q.Ref(q.Collection("tasks"), taskData.ref.value.id)],
              q.Var("array")
            ),
          },
        })
      )
    );
    return taskData;
  } catch (err) {
    console.error(err);
  }
};
export default createTask;

Copy the code

First, the data is inserted into the task collection.

const taskData = await client.query(
      q.Create(q.Collection("tasks"), {
        data: {
          name,
          description,
          projectId,
        },
      })
    );

Copy the code

Next, add the task ID to the project collection.

let res = await client.query(
      q.Let(
        {
          projectRef: q.Ref(q.Collection("projects"), projectId),
          projectDoc: q.Get(q.Var("projectRef")),
          array: q.Select(["data", "tasks"], q.Var("projectDoc"), []),
        },
        q.Update(q.Var("projectRef"), {
          data: {
            tasks: q.Append(
              [q.Ref(q.Collection("tasks"), taskData.ref.value.id)],
              q.Var("array")
            ),
          },
        })
      )
    ); 

Copy the code

The [Let] (https://docs.fauna.com/fauna/current/api/fql/functions/let?lang=javascript) function will be one or more variables bound to a single value or an expression.

Update data in Fauna

To update the data in Fauna, use the following query.

await client.query(
      q.Update(q.Ref(q.Collection("projects"), projectId), {
        data: { description },
      })
    );

Copy the code

We’ve covered all the features involved in CRUD applications using Firebase and Fauna. You can find the full source code for this example on GitHub.

Now that we know how they work, let’s compare Firebase and Fauna and summarize their pros and cons.

Firebase and Fauna

Before we start comparing Firebase and Fauna, it’s worth noting that these are just my opinions based on personal preference, my own analysis, and my experience in building the examples above. Others may disagree, so you’re welcome to voice your opinions in the comments.

The learning curve

Firebase is easy to learn and adapt to because most of its functions are similar to those of JavaScript. For example.

  • get()Retrieve data from Firebase
  • set()Insert data into Firebase
  • update()Update data in Firebase

Fauna, on the other hand, has a pretty steep learning curve. You can use the GraphQL or Fauna query language (FQL). It takes some time to understand these concepts and learn how FQL works. However, once you have a good grasp of it, it becomes easy to write complex queries in less time.

Settings and scalability

Both Firebase and Fauna are straightforward to set up on the client. Both databases are designed for building scalable back-end solutions. Fauna is, in my opinion, a better choice for building complex applications. I’ll explain why in a minute.

Fauna works well with GraphQL and can provide services with a low latency global CDN. Compared to Fauna, Firebase is fast, responsive and easy to set up.

Complex queries and operations

As your application grows, you may encounter the need to write complex queries such as.

  • Get the summarized data to generate the report
  • Payment processing
  • Transactional query
  • The aggregation

As you can see from our example above, Fauna can effectively handle complex queries and operations. Fauna is a distributed database and can be a relational, document, and graphical database.

One of Fauna’s key features is its ability to handle ACID transactions, which is why it can easily handle complex queries.

For example, functions in Fauna, such as Lambda(),Let(), and Select(), enable you to write powerful queries with less code.

The price

Fauna’s free layer includes 100,000 reads, 50,000 writes, and 500,000 computational operations. For individual businesses, $23 a month covers most operations.

Firebase includes 50,000 reads, 20,000 writes, and 1GB of storage, which covers operations. It’s based on a “pay as you go” model.

Support and Community

Both Firebase and Fauna are well supported and documented. Compared to Fauna, the Firebase community is mature and large because it is widely used by web and mobile developers. Fauna has excellent documentation to help you easily understand the basic concepts.

Firebase vs. Fauna. Which is better?

If you plan to use fewer complex queries and need to build an application quickly, Firebase is a better fit. Therefore, it is a good choice when your application has limited integration. Also, if you need to develop a quick prototype or small-scale application in a short amount of time, Firebase is the best solution because it includes batteries.

Fauna is ideal when your application needs a high degree of scalability in handling complex queries. It can handle a multi-model database, all of which can be retrieved from a single query. Fauna is especially useful if you need to build a scalable application that can handle relational database structures. Please note, however, that Fauna does not provide an internal corporate database.

The postFirebase and Fauna: Database tool comparison for front-end developers first appeared on The LogRocket blog.