Firebase Cloud Functions — What It Is, Triggers, and How to Write Functions

Author: IT Sectr Published: 2026-04-28 Reading time: 15 min

Firebase Cloud Functions is a server-side platform for running code in a managed Node.js environment that responds to Firebase events, HTTPS requests, and changes in Google Cloud services. Unlike traditional backends, developers do not need to configure a server, install a web server, or worry about scaling — each function runs in an isolated container and automatically gets as many resources as needed. According to Google Firebase (2026), the platform processes over 2 billion function calls daily, providing a serverless architecture for millions of mobile applications.

Key Takeaways

  • Cloud Functions is server-side code that executes in response to Firebase events and HTTPS requests.
  • Serverless model eliminates infrastructure management: scaling happens automatically.
  • Triggers include changes in Firestore, Realtime Database, Storage, Authentication, and Pub/Sub.
  • Development language — JavaScript, TypeScript, or Python (via Google Cloud Functions).
  • Cold start — the first call after inactivity can take up to 2 seconds.

What Are Firebase Cloud Functions and How They Work

Firebase Cloud Functions is a computing platform built on top of Google Cloud Functions (GCF), adapted for the Firebase ecosystem. Functions are regular JavaScript or TypeScript code exported from a module and registered for a specific event type. When an event occurs (for example, a user registers or uploads a file), Firebase Cloud Functions runs the corresponding code, passing it the event context.

The Cloud Functions architecture follows the single responsibility principle: one function handles one event type and performs one atomic operation. For example, the sendWelcomeEmail function is triggered when a new user is created in Firebase Authentication and sends a welcome email. Such isolation simplifies debugging, testing, and reusing functions across different projects.

Each function runs in an isolated container with a temporary lifecycle. The maximum execution time defaults to 60 seconds (HTTPS functions — 9 minutes). If a function does not complete within the timeout, the request fails with error 500. For long-running operations, use Cloud Tasks or Pub/Sub with retries. Containers can be reused for subsequent calls (keep-alive), which reduces latency on cold starts after the first call.

Runtime Environment and Node.js Versions

Firebase Cloud Functions supports several Node.js versions: 18, 20, and 22 (recommended for new projects). The version is specified in the engines field of the package.json file. Firebase CLI automatically configures the runtime environment based on the specified version. Importantly, Firebase Cloud Functions does not support running arbitrary Docker containers — the environment is strictly fixed by Google Cloud Functions.

For new projects, Node.js 22 is recommended, as it includes the latest V8 optimizations, improved ESM module support, and WebSocket support at the platform level. If a project uses dependencies built for a specific Node version (e.g., native C++ modules), compatibility must be checked individually — not all native modules compile under the GCF environment.

Difference Between Firebase Cloud Functions and Google Cloud Functions

Firebase Cloud Functions is a wrapper around Google Cloud Functions with pre-installed Firebase SDK and integration with Firebase services. The developer writes code using the firebase-functions SDK, which provides typed triggers for all Firebase services. Google Cloud Functions is a lower-level platform where triggers are configured through Eventarc or Pub/Sub explicitly.

The key difference: in Firebase Cloud Functions, a trigger is registered declaratively via functions.firestore.document('path').onWrite(), while in Google Cloud Functions it is configured through Eventarc with event attribute filtering. Firebase Cloud Functions also comes with the Admin SDK automatically initialized with the project's service account credentials, providing full access to all Firebase services without additional setup.

Types of Triggers: Which Events Are Supported

Firebase Cloud Functions supports 8 categories of triggers, each corresponding to a specific Firebase or Google Cloud service. A trigger is a condition that automatically invokes a function when met. The developer does not manage the function lifecycle directly: Firebase CLI registers the trigger in Google Cloud Eventarc, and the cloud platform runs the function when the event occurs.

The most popular triggers are Firestore triggers: onWrite, onCreate, onUpdate, onDelete. They fire when documents in Firestore collections change. The function receives document snapshots before and after the change, allowing comparison of values and response to only specific changes. For example, when an order status changes from “pending” to “shipped”, a push notification can be sent to the user.

Authentication triggers (onCreate, onDelete) fire when a user account is created or deleted. They are used for initializing user data: creating a user document in Firestore, sending a welcome email, writing to analytics. Note: the function cannot cancel user creation — it executes after the account is already created. For pre-validation, use Blocking Functions available on the Identity Platform.

Trigger CategoryEventUse Case Example
FirestoreonWrite, onCreate, onUpdate, onDeleteUpdating like counter when a like is added
AuthenticationonCreate, onDeleteCreating user profile on registration
Realtime DBonWrite, onCreate, onUpdate, onDeleteChat message moderation
StorageonFinalize, onArchive, onDeleteGenerating thumbnail after image upload
Pub/SubonPublishScheduled execution (cron) via Cloud Scheduler
HTTPSonRequestREST API endpoint for external services

HTTPS Triggers and CORS

HTTPS functions (onRequest) allow creating full REST API endpoints accessible via HTTP. Unlike event-driven triggers, HTTPS functions are called via a URL of the form https://{region}-{project}.cloudfunctions.net/{functionName}. It is important to configure CORS correctly if the endpoint is called from a browser or mobile application. The Firebase SDK does not include CORS headers automatically — they must be added manually via middleware.

For mobile clients (Android, iOS), CORS is not required since native HTTP clients are not restricted by the Cross-Origin policy. CORS is only relevant for web requests. If your HTTPS function is called from both the app and the web, add universal CORS handling: res.set('Access-Control-Allow-Origin', '*') for development or a list of allowed domains for production.

Scheduling with Pub/Sub and Cloud Scheduler

For periodic execution (cron jobs), use a combination of Cloud Scheduler and Pub/Sub. Cloud Scheduler sends a message to a Pub/Sub topic on a schedule, and the Cloud Functions onPublish trigger processes that message. Firebase CLI does not support direct cron syntax — the schedule is configured via the Google Cloud console or Terraform in unix-cron format: 0 3 * * * (every day at 3:00).

Example tasks: daily newsletter, cleaning up outdated data, generating reports, synchronizing with external APIs. Important: Cloud Scheduler is a paid Google Cloud service (about $2 per month per job). Each trigger counts as a separate function call and is billed at standard Cloud Functions rates.

How to Write and Deploy Functions

Cloud Functions development starts with initializing a project via Firebase CLI: firebase init functions. This command creates a functions/ directory with an index.js (or index.ts) template, a package.json file, and TypeScript configuration (if selected). After initialization, simply write a function, export it from the module, and run firebase deploy --only functions to deploy.

Each function is registered by calling the appropriate trigger method. Example of an HTTPS function: exports.helloWorld = functions.https.onRequest((req, res) => { res.send(“Hello!”); }). Firebase Functions use an asynchronous model: for event-driven triggers (non-HTTPS), the function must return a Promise. Firebase waits for the Promise to complete before terminating the container. If a Promise is not returned, the function may be terminated before async operations finish.

Local development is done through the Firebase Emulator Suite, which includes a Cloud Functions emulator. The command firebase emulators:start starts a local server with functions accessible at http://localhost:5001. The emulator supports hot reload when code changes and is fully isolated from the production environment, allowing testing without risk to real data.

Dependency and Configuration Management

Dependencies for Cloud Functions are managed through package.json. Firebase installs only production dependencies (dependencies, not devDependencies). The function package size affects cold start time: it is recommended to minimize the number of dependencies. The firebase-admin dependency is pre-installed for Firebase Admin SDK — it does not need to be added manually.

Confidential data (API keys, tokens) should not be stored in function code. Use functions.config() for storing configuration: firebase functions:config:set stripe.key=“sk_...”. Values are encrypted and available at runtime via functions.config().stripe.key. For large serialized configurations, use Google Cloud Secret Manager.

Error Handling and Logging

Logging in Cloud Functions is done through console.log, console.warn, and console.error. All logs are automatically collected in Google Cloud Logging and are available in the Firebase console (Functions > Logs). For structured logging, use the winston or pino libraries, which support JSON formatting and log levels.

Error handling is critical for reliability: an unhandled exception in a Promise terminates the function with an error, after which Firebase automatically retries with exponential backoff. The number of retries is configurable: from 0 to infinity. For event-driven triggers, it is recommended to enable retry to ensure every event is processed even during temporary external service failures.

Cold Start and Scaling

Cold start is the delay on the first invocation of a function after a period of inactivity, when the code container is loaded and initialized anew. According to Firebase documentation (2026), a cold start takes from 200 ms to 2 seconds depending on package size, number of dependencies, and region. For the user interface, a delay exceeding 1 second is noticeable and can affect user experience.

Ways to minimize cold start: minimize dependencies, use TypeScript compiled to CommonJS, reduce function package size, set a minimum number of active instances. Firebase Cloud Functions v2 (2nd gen) allows setting minInstances — the minimum number of warm containers always ready to process requests. Keeping containers warm incurs charges for idle time.

Scaling of Cloud Functions happens automatically: as request volume increases, Firebase creates new containers. By default, the maximum number of parallel instances is 3000 (Google Cloud project quota). Each instance handles one request at a time. If a function is fast (under 100 ms), one instance can handle up to 10 requests per second, providing a peak throughput of up to 30,000 requests per second per project.

Configuring minInstances and maxInstances

minInstances is a parameter that reserves a specified number of containers and keeps them warm. It is recommended for critical HTTPS functions where cold start latency is unacceptable. For example, for an authentication endpoint, set minInstances: 1. maxInstances limits the maximum number of parallel instances, useful for preventing uncontrolled cost growth during sudden traffic spikes.

Configuration is done in code: functions.runWith({ minInstances: 1, maxInstances: 10 }). Important: minInstances increases cost because containers run continuously. For test projects, minInstances should be disabled. For production, minInstances is recommended for all public HTTPS functions and 0 for event-driven triggers where a 1-second delay is not critical.

Deployment Regions

Deployment region affects latency to end users and the cost of outgoing traffic. Firebase Cloud Functions are available in 30+ Google Cloud regions. For mobile applications, choose the region closest to your target audience: us-central1 for the Americas, europe-west1 for Europe, asia-east2 for Asia. The region cannot be changed after deployment without redeploying the function.

Changing the region is done via the region parameter in code: functions.region('europe-west1'). All functions in one file can have different regions. For global projects, it is recommended to deploy functions in multiple regions and use Cloud Load Balancing for traffic distribution, although for most mobile applications a single region is sufficient if chosen correctly.

Code Examples for Firebase Cloud Functions

Let us look at practical examples of Cloud Functions in TypeScript. The code uses Firebase Functions SDK v2 (2nd gen) with ES module syntax. Examples include handling a user creation event, generating a thumbnail on image upload, and a simple HTTPS endpoint for a REST API. All functions are asynchronous and return a Promise for proper container termination.

Before running, make sure Firebase CLI is updated to version 13+: npm install -g firebase-tools. Functions v2 require the Blaze pricing plan. Initialization: firebase init functions with TypeScript selected.

Handling User Registration

The first example — creating a document in Firestore when a new user registers. The function is triggered by the auth.user().onCreate event and writes a basic profile to the users/{uid} collection. This ensures that every registered user has a document with the necessary fields.

typescript
import * as functions from "firebase-functions"
import * as admin from "firebase-admin"

admin.initializeApp()

export const createUserProfile = functions.auth
    .user()
    .onCreate(async (user) => {
        const profile = {
            email: user.email,
            displayName: user.displayName ?? "User",
            createdAt: admin.firestore.Timestamp.now(),
            role: "free",
            avatarUrl: null,
        }

        await admin.firestore()
            .collection("users")
            .doc(user.uid)
            .set(profile)

        console.log(`Profile created for ${user.uid}`)
    })

The createUserProfile function is asynchronous — it returns a Promise that Firebase waits for before terminating. If writing to Firestore fails (e.g., due to insufficient permissions), the function will be automatically retried (if retry is enabled). The role field with a value of “free” allows implementing free tier restrictions directly in Firestore Security Rules by comparing resource.data.role with the required access level.

Generating Thumbnails on Image Upload

The second example — a Storage trigger for automatically generating a thumbnail after an image is uploaded. The function creates a reduced copy sized 200x200 pixels and saves it to the original file's path with a thumb_ prefix. Image processing uses the sharp library, which supports all common formats and works in the Node.js environment without system dependencies.

typescript
import * as path from "path"
import * as os from "os"
import * as sharp from "sharp"

export const generateThumbnail = functions.storage
    .object()
    .onFinalize(async (object) => {
        if (!object.contentType?.startsWith("image/")) return

        const filePath = object.name!
        const thumbPath = filePath.replace(
            /(\.\w+)$/, "_thumb$1"
        )

        const bucket = admin.storage().bucket()
        const tempDir = os.tmpdir()
        const tempFile = path.join(tempDir, path.basename(filePath))

        await bucket.file(filePath).download({ destination: tempFile })
        await sharp(tempFile)
            .resize(200, 200, { fit: "cover" })
            .toFile(tempFile.replace(/(\.\w+)$/, "_thumb$1"))

        await bucket.upload(tempFile.replace(
            /(\.\w+)$/, "_thumb$1"
        ), { destination: thumbPath })
    })

The generateThumbnail function checks the object's Content-Type and ignores non-images, saving resources. To use sharp, the dependency must be added to package.json. The thumbnail is created with the fit: “cover” parameter, which crops the image from the center to a 200x200 pixel square. After creation, the thumbnail is uploaded back to the same bucket with a modified name.

HTTPS Endpoint for a Public API

The third example — an HTTPS function implementing a REST API endpoint for checking server status. The function accepts a GET request and returns JSON with information about the state of Firebase services connected to the project. This endpoint is useful for monitoring and external systems that need to verify backend availability before sending data.

typescript
import * as express from "express"

const app = express.Router()

app.get("/status", async (req, res) => {
    try {
        const db = admin.firestore()
        await db.collection("_health").doc("check").get()
        res.json({ status: "ok", timestamp: Date.now() })
    } catch (error) {
        res.status(503).json({ status: "error", message: error })
    }
})

export const api = functions.https.onRequest(app)

The api function uses express Router for routing, which is convenient when creating multiple endpoints in a single function. The health check writes to Firestore in the _health collection, allowing simultaneous verification of Firestore availability. For production, it is recommended to add request authentication via an API key or Firebase Auth token to prevent abuse of the public endpoint.

Typical Use Cases in Mobile Applications

Cloud Functions are most commonly used for tasks that cannot or should not be performed on the client: sending push notifications, generating previews of uploaded images, integrating with external payment systems, content moderation, synchronizing data between Firebase and third-party services. The serverless model makes these tasks cost-effective: you pay only for the actual code execution time.

Payment system integration is a typical scenario for apps with in-app purchases. Cloud Functions receives a webhook from the payment provider (Stripe, PayPal), verifies the request signature, updates the subscription status in Firestore, and sends a confirmation to the user. All code runs on the server without risk of data tampering on the client. According to Stripe documentation (2026), webhook processing takes under 500 ms.

Smart content moderation uses a Cloud Function Storage trigger to automatically check uploaded images via the Google Cloud Vision API. The function sends the image to Vision API for unsafe content detection (violence, adult content) and, if the threshold is exceeded, deletes the file and notifies the administrator. This scenario is critical for UGC applications with user galleries.

Data aggregation — Cloud Functions as a replacement for Firebase Realtime Database counters. Instead of reading and writing a counter on the client (which leads to race conditions), use a Firestore onWrite trigger for atomic updates of aggregated fields. For example, a function counts the number of post likes each time a document is added or removed in the /posts/{postId}/likes/{userId} subcollection and updates the likesCount field in the parent document.

Frequently Asked Questions

How long can a single function run?

Maximum execution time depends on the type: HTTPS functions — 9 minutes, event-driven triggers — 60 seconds (v2: up to 60 minutes). For long-running operations, use Cloud Tasks or Pub/Sub with asynchronous processing. The timeout is configured in code via runWith({ timeoutSeconds: 120 }).

How to debug Cloud Functions locally?

Use the Firebase Emulator Suite: firebase emulators:start --only functions. The emulator runs functions locally on port 5001 with hot reload support. For Firestore and Auth triggers, the emulator replaces real services, allowing scenario testing without risk to production data.

What is the difference between 1st gen and 2nd gen functions?

2nd gen uses Google Cloud Run and Eventarc, providing a longer timeout (up to 60 minutes), concurrent request handling by a single instance, and improved integration with Google Cloud services. 1st gen uses Google Cloud Functions and is limited to 60 seconds for event-driven functions. Firebase recommends starting new projects with 2nd gen.

Can I use Python instead of JavaScript?

Firebase Cloud Functions officially supports only Node.js (JavaScript and TypeScript). For Python, use Google Cloud Functions directly with the Firebase Admin SDK for Python. The Firebase Admin SDK Python supports all operations except some Firebase-specific triggers that are only available through Node.js.

How to protect an HTTPS function from unauthorized access?

For authenticated access, verify the Firebase ID token in the Authorization header: admin.auth().verifyIdToken(token). For server-to-server integration, use the Firebase Admin SDK with a service account or API keys. For public endpoints with rate limiting, use rate limiting via Cloud Armor or middleware.

Summary

  • Firebase Cloud Functions — a serverless platform for running code in response to Firebase events and HTTPS requests.
  • Triggers are supported for Firestore, Authentication, Storage, Realtime Database, Pub/Sub, and HTTPS.
  • Cold start — the main drawback: up to 2 seconds delay on the first call after inactivity, mitigated by minInstances.
  • Scaling happens automatically up to 3000 parallel instances, with pay-per-execution pricing.
  • Development is done in JavaScript/TypeScript with local testing via the Firebase Emulator Suite.
  • Function code follows the single responsibility pattern: one function — one event type.
  • Security of configuration data is ensured via functions.config() or Google Cloud Secret Manager.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also