---
title: "Sending Push Notifications from Replit with Firebase"
description: "Learn how to send push notifications from Replit using Firebase Cloud Messaging (FCM) with TypeScript or Python. This guide covers service account setup, storing secrets securely in Replit, complete code examples for both languages, and troubleshooting common issues like invalid tokens and permission errors."
image: "https://cdn.sethserver.com/blog-images/sending-push-notifications-from-replit-with-firebase-social.webp"
---

# Sending Push Notifications from Replit with Firebase

I've been shipping small tools on Replit for years now. It's perfect for those side projects that need to go from idea to production in an afternoon. And lately I've been building more tools that run background jobs. Those jobs finish whenever they feel like it, which means users either refresh a page like it's 2004... or you notify them.

When one of those projects needs to ping users, Firebase Cloud Messaging (FCM) is my go-to. No servers to maintain, no message queues to debug, it's an API that just works. It's not "magic," but it's close enough that I'll allow it.

This post shows how to send an FCM push notification from a Replit backend using either TypeScript (Node) or Python.

Firebase docs for context: [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging)

---

## What you need (in human terms)

You'll need:

A Firebase project with Cloud Messaging enabled. This is where Firebase tracks your app, your credentials, and your ability to send messages without being escorted out of the building.

A service account key JSON file. This is the important one for server-side sending. Firebase uses it to verify you're actually you, and not some random person trying to spam notifications. (Yes, the JSON is annoyingly large.)

A device token from the client you're targeting (mobile app, web app, etc). This is basically the "address" you're sending the notification to. Also: tokens expire, rotate, and generally behave like they have free will.

A Replit project running Node/TypeScript and/or Python.

One thing that got me the first time: make sure you're using the **service account key**, not the **web API key**. They look like they belong together, but they do completely different jobs. The web API key won't work for server-side sending, and you'll waste time thinking you made a coding mistake. (You didn't. Firebase just enjoys ambiguity.)

---

## Store secrets safely in Replit (so you don't create your own incident report)

In Replit, open **Secrets** and add:

- `FIREBASE_SERVICE_ACCOUNT_JSON` = paste the full JSON contents of the service account key
- `FCM_DEVICE_TOKEN` = a test device token (optional, but handy)

Don't commit this JSON file to your repo. I've seen too many [startups learn this lesson the expensive way](https://www.sethserver.com/startups/what-is-a-startup.html) when their Firebase bill explodes because someone scraped their public GitHub repo. "We got hacked" is rarely a fun meeting, especially when it was actually "we published our keys."

---

## TypeScript example (Node)

Install the Admin SDK:

```bash
npm i firebase-admin
```

Send a notification:

```ts
import admin from "firebase-admin";

// Parse the JSON we stored in Replit secrets.
// If you pasted it wrong (missing a quote/brace), Node will let you know immediately.
// It will also ruin your whole day.
const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT_JSON!);

// Firebase needs this check or it'll initialize multiple times and throw errors,
// especially in serverless-ish or hot-reload-ish environments.
if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
  });
}

export async function sendPush(token: string) {
  const message = {
    token,

    // notification = what most platforms show by default (title/body)
    notification: {
      title: "Hello from Replit",
      body: "This came from Firebase Cloud Messaging.",
    },

    // data = extra key/value pairs your app can read
    // Useful when you want the client to navigate somewhere, refresh state, etc.
    data: {
      source: "replit",
      kind: "job_finished",
    },
  };

  const res = await admin.messaging().send(message);
  console.log("Sent:", res);
}

sendPush(process.env.FCM_DEVICE_TOKEN!);
```

### Notes that save hours (because I've donated those hours already)

I've burned a bunch of hours on permission errors. Double-check that your service account actually has the right access. In many setups, you want something like **Firebase Cloud Messaging Admin** permissions. If you're seeing `PERMISSION_DENIED`, it's almost never "a bug in your code." It's IAM.

Also yes, tokens expire. I spent an multiple afternoons debugging code that was perfectly fine. The token had expired overnight. I changed nothing. Reality changed around me. This happens with Google oAuth tokens too. You're welcome.

---

## Python example

The Python version is nearly identical, which is actually kind of nice. Firebase keeps their SDKs consistent across languages. (If only every vendor did that, half of us could retire early.)

Install:

```bash
pip install firebase-admin
```

Send a notification:

```py
import os
import json
import firebase_admin
from firebase_admin import credentials, messaging

# Parse the JSON we stored in Replit secrets.
# If you accidentally pasted the wrong thing, json.loads will fail loudly (as it should).
service_account = json.loads(os.environ["FIREBASE_SERVICE_ACCOUNT_JSON"])

# Firebase needs this check or it'll initialize multiple times and throw errors.
if not firebase_admin._apps:
    cred = credentials.Certificate(service_account)
    firebase_admin.initialize_app(cred)

def send_push(token: str):
    msg = messaging.Message(
        token=token,
        notification=messaging.Notification(
            title="Hello from Replit",
            body="Python says hi via FCM."
        ),
        # Data payload is great for app routing, background refresh, etc.
        data={"source": "replit", "kind": "job_finished"},
    )

    resp = messaging.send(msg)
    print("Sent:", resp)

send_push(os.environ["FCM_DEVICE_TOKEN"])
```

Python-specific gotcha I've hit: make sure you're not mixing up environment variables between local and Replit runs. Locally you might have a `.env` file or shell exports, and on Replit you're using Secrets. When it "works on my machine" here, it usually means "my machine had the env var and Replit didn't."

---

## Troubleshooting (the non-theoretical kind)

If you're getting **Invalid token** errors, your client token is either wrong or expired. Tokens don't last forever, and they can change when the app reinstalls, clears data, or refreshes registration.

If notifications aren't showing up, check if your app is in the foreground. Most mobile OSes won't show a notification banner for the active app. Your message may still arrive, but you'll need client-side handlers to display it or update UI.

If it works locally but not in Replit, you probably fat-fingered the JSON when pasting it into secrets. Missing a closing brace will ruin your whole day. Also double-check you pasted the **service account JSON** and not some other Firebase credential. Firebase has several keys, and only one of them is the one you want here.

---

## Wrap-up

Push notifications used to require standing up your own infrastructure or paying for expensive third-party services. Firebase turned it into a straightforward API call with generous free tier limits. For most [side projects and early-stage startups](https://www.sethserver.com/startups/what-is-a-startup.html), that's exactly what you need: simple, reliable, and not another system you have to babysit.

-Sethers


```json
{"@context": "https://schema.org", "@type": "BlogPosting", "headline": "Sending Push Notifications from Replit with Firebase", "datePublished": "2026-01-15T20:31:57", "dateModified": "2026-09-17T19:48:10", "image": {"@type": "ImageObject", "url": "https://cdn.sethserver.com/blog-images/sending-push-notifications-from-replit-with-firebase-social.webp", "width": 400, "height": 400}, "url": "https://www.sethserver.com/programming/sending-push-notifications-from-replit-with-firebase.html", "author": {"@type": "Person", "name": "Seth Black", "url": "https://www.linkedin.com/in/seth-black-tx"}, "publisher": {"@type": "Organization", "name": "Sethserver", "logo": {"@type": "ImageObject", "url": "https://www.sethserver.com/static/images/PaperAirplane512.png"}}, "description": "Learn how to send push notifications from Replit using Firebase Cloud Messaging (FCM) with TypeScript or Python. This guide covers service account setup, storing secrets securely in Replit, complete code examples for both languages, and troubleshooting common issues like invalid tokens and permission errors.\r\n", "articleSection": "Technology"}
{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{"@type": "ListItem", "position": 1, "name": "sethserver", "item": "https://www.sethserver.com/"}, {"@type": "ListItem", "position": 2, "name": "Programming", "item": "https://www.sethserver.com/programming/"}, {"@type": "ListItem", "position": 3, "name": "Sending Push Notifications from Replit with Firebase", "item": "https://www.sethserver.com/programming/sending-push-notifications-from-replit-with-firebase.html"}]}
```
