Firebase Tutorial: Real-Time Chat

Learn to build a chat app with Firebase and MessageKit! By Yusuf Tör.

Leave a rating/review
Download materials
Save for later
Update note: Yusuf Tör updated this tutorial for iOS 14, Swift 5, Xcode 12 and MessageKit 3.6. Tom Elliott wrote the original.

It seems like every major app out there has a chat feature, and yours should be no different! This Firebase tutorial will show you how to add real-time chat to your app.

However, creating a chat tool can seem like a daunting task. There are no native UIKit controls specifically designed for chat, and you need a server to coordinate and store the conversations between users.

Fortunately, there are some great frameworks out there to help you:

  • Firebase lets you synchronize real-time data without writing a line of server code.
  • MessageKit gives you a messaging UI that’s on par with the native Messages app.

In this tutorial, you’ll build RWRC, or Ray Wenderlich Relay Chat, an anonymous chat app. If you’ve used IRC or Slack, you’re already familiar with this sort of app.

A conversation thread about puppies

Along the way, you’ll learn how to:

  • Authenticate anonymously with Firebase.
  • Create multiple chat channels.
  • Leverage MessageKit for a complete chat UI.
  • Synchronize data in real-time with the Firestore database.
  • Use Firebase Storage to send pictures.

Getting Started

Click Download Materials at the top or bottom of this tutorial to download the starter project.

Open the starter project and take a quick look around. The starter project contains a simple dummy login screen that saves the credentials to UserDefaults. It also has a few helper classes for sending data to Firebase and saving data to UserDefaults.

In the starter project, you’ll find ChannelsViewController.swift, which listens to changes in a Firebase Firestore database and updates a table view whenever the user adds a new channel. You’ll build a similar implementation to display chat messages instead of channels.

You’ll find the Firebase SDK and MessageKit are already in the project as Swift Packages. These will automatically install when you open the project.

Note: If you’re new to the Swift Package Manager, check out our Introduction to Swift Package Manager tutorial for an in depth explanation.

Before you can run the app, you’ll need to configure Firebase.

Creating a Firebase Account

If you’re new to Firebase, you’ll need to create an account. Don’t worry! It’s easy and free.

Head to the Firebase signup site and create an account. Then create and name a new Firebase project called RWRC. Make sure that you disable support for Google Analytics as it won’t be necessary for this tutorial.

Note: For a detailed walk-through on setting up Firebase, see the Getting Started with Firebase Tutorial.

In Xcode, click the target and change the Bundle Identifier to any value you like. Then select a Team in the Signing section.

In the Project Overview in Firebase, click iOS. You’ll see instructions to add Firebase to your iOS app:

Add Firebase to iOS app

Next, enter the app’s bundle ID (the one you chose earlier in Xcode) and name (RWRC) into the form and click Register app:

Register bundle ID and app name with Firebase

Download and add GoogleService-Info.plist to your project under the Supporting Files group as shown in the Firebase instructions. This file contains the configuration information you need to integrate Firebase with your app:

Download config file

Note: Do only steps one and two of the instructions. The rest is already done in the starter project and your app will crash if you duplicate the steps.

Now build and run. You’ll see the following:

Login screen

That’s a good start, but right now the application login screen doesn’t actually do anything. You’ll now hook that up to Firebase.

Enabling Anonymous Authentication

Firebase lets users log in through email or social accounts. However, it can also authenticate users anonymously, giving them unique identifiers without knowing their personally identifiable information.

To set up anonymous authentication, open the Firebase console for the app you made earlier. Select Authentication on the left and click Get started:

Firebase authentication console

Then select Anonymous. Toggle Enable and click Save:

Enabling anonymous authentication

Just like that, you enabled super secret stealth mode! Okay, so it’s just anonymous authentication. But hey, it’s still cool. :]

Stealth Swift

It’s now time to set up the login within the app itself.

Logging In

Open LoginViewController.swift. Under import UIKit, add:

import FirebaseAuth

To log in to chat, the app will need to authenticate using the Firebase authentication service. Add the following code to the end of signIn():


This method asynchronously logs into Firebase anonymously. If the device has already signed in, then the existing user is signed in, otherwise a new user is created. Once the sign in has completed Firebase posts the AuthStateDidChange notification that AppController is listening for. AppController updates the root view controller for you when the notification fires.

Build and run. Enter a display name and tap Get Started:

Empty channel list

Once the user signs in, they automatically navigate to the ChannelsViewController. They’ll see a list of current channels and have the option to create new channels. The table has a single section to display all available channels.

At the bottom, they’ll see a toolbar with a sign-out button, a label displaying their name and an add button.

Before you dive into sending messages in real-time, take a minute to learn about the databases Firebase has to offer.

Choosing a Firebase Database

Firebase comes with two NoSQL JSON databases: Firestore and Realtime Database.

Initially, Firebase only had Realtime Database, an efficient, low-latency database that stores data in one big JSON tree.

However, this wasn’t the best solution for all use cases. So the Firebase team improved on the success of Realtime Database with a new, more intuitive data model called Firestore.

Firestore stores data as documents that contain a set of key-value pairs. It organizes these documents into collections. Each document can have sub-collections.

Each database has strengths and weaknesses.

The Realtime Database:


  • Supports user presence, so you can tell when a user is online or offline.
  • Has extremely low latency.
  • Charges for bandwidth and storage but not for operations performed in the database.
  • Scales to 200k concurrent connections.


  • Has no multi-region support. Data is available in regional configurations only.
  • Has limited sorting and filtering functionality.

The Firestore database:


  • More structured than the Realtime Database and can perform more complex queries on the data.
  • Designed to scale better than the Realtime Database. The scaling limit is currently around one million concurrent connections.
  • Has multiple data centers storing data in distinct regions and can support multi-regional configurations.
  • Charges primarily on operations performed in the database and, at a lower rate, bandwidth and storage.


  • Doesn’t allow documents to update at a rate greater than once per second.
  • Doesn’t support user presence.

For this tutorial, you’ll use Firestore as your database. However, in a production chat app with lots of reads and writes to the database, you may choose the Realtime Database to reduce costs.

You can also use both the Firestore and Realtime Database within your app. For more information about these databases, take a look at Firebase’s documentation.

Now that you know a little about the Firebase database, it is time to learn about the structure of the data you’ll store in the database.