Firebase Scheduled Functions
Scheduled functions run automatically at a time you define — like an alarm clock for your server code. Use them for sending daily digest emails, clearing expired data, generating weekly reports, or syncing data from external APIs. No user interaction is needed to trigger them.
The Automatic Sprinkler Analogy
A garden sprinkler system waters the lawn at 6 AM every day without anyone turning it on manually. Scheduled Cloud Functions work the same way — you set the schedule once and Firebase runs the function on time, every time, whether you are awake or not.
Creating a Scheduled Function
const { onSchedule } = require("firebase-functions/v2/scheduler");
const admin = require("firebase-admin");
admin.initializeApp();
// Run every day at midnight UTC
exports.dailyCleanup = onSchedule("every 24 hours", async (event) => {
const db = admin.firestore();
const cutoff = new Date();
cutoff.setDate(cutoff.getDate() - 30); // 30 days ago
// Delete notifications older than 30 days
const snapshot = await db.collection("notifications")
.where("createdAt", "<", cutoff)
.get();
const batch = db.batch();
snapshot.docs.forEach((doc) => batch.delete(doc.ref));
await batch.commit();
console.log("Deleted", snapshot.size, "old notifications.");
});
Schedule Syntax
Firebase scheduled functions accept two schedule formats:
App Engine Cron Format
"every 5 minutes" "every 1 hours" "every 24 hours" "every monday 09:00" "every day 08:00"
Unix Cron Expression
"0 * * * *" // every hour on the hour "0 9 * * 1" // every Monday at 9:00 AM "0 0 1 * *" // first day of every month at midnight "*/15 * * * *" // every 15 minutes "0 8,12,18 * * *" // at 8 AM, 12 PM, and 6 PM daily
Unix cron expressions use five fields: minute, hour, day of month, month, day of week.
Setting a Timezone
By default, schedules run in UTC. Specify a timezone for time-sensitive schedules:
exports.morningReport = onSchedule(
{
schedule: "every day 09:00",
timeZone: "Asia/Kolkata" // IST
},
async (event) => {
console.log("Generating morning report at 9 AM IST");
await generateDailyReport();
}
);
Use IANA timezone names like America/New_York, Europe/London, Asia/Tokyo, or Asia/Kolkata.
Practical Example: Weekly Email Digest
const { onSchedule } = require("firebase-functions/v2/scheduler");
const admin = require("firebase-admin");
exports.weeklyDigest = onSchedule(
{ schedule: "every monday 08:00", timeZone: "America/New_York" },
async (event) => {
const db = admin.firestore();
// Get all users subscribed to the digest
const usersSnap = await db.collection("users")
.where("digestEnabled", "==", true)
.get();
const lastWeek = new Date();
lastWeek.setDate(lastWeek.getDate() - 7);
// Get last week's top posts
const postsSnap = await db.collection("posts")
.where("publishedAt", ">=", lastWeek)
.orderBy("publishedAt", "desc")
.limit(5)
.get();
const topPosts = postsSnap.docs.map((d) => d.data().title);
// Send digest to each subscriber
for (const user of usersSnap.docs) {
await sendDigestEmail(user.data().email, topPosts);
}
console.log("Weekly digest sent to", usersSnap.size, "users.");
}
);
Practical Example: Expiring Trial Accounts
exports.checkTrialExpiry = onSchedule("every 24 hours", async () => {
const db = admin.firestore();
const now = new Date();
const snapshot = await db.collection("users")
.where("plan", "==", "trial")
.where("trialEndsAt", "<=", now)
.get();
const batch = db.batch();
snapshot.docs.forEach((doc) => {
batch.update(doc.ref, { plan: "free", trialExpired: true });
});
await batch.commit();
console.log("Expired", snapshot.size, "trial accounts.");
});
Monitoring Scheduled Functions
View execution logs in the Firebase Console under Functions > Logs. Filter by function name to see when it ran, how long it took, and whether it succeeded or threw an error. Set up alerts for function errors in Google Cloud Monitoring for critical scheduled tasks.
Retry on Failure
Enable automatic retry if a scheduled function fails:
exports.criticalJob = onSchedule(
{
schedule: "every 24 hours",
retryConfig: {
retryCount: 3,
minBackoffSeconds: 10
}
},
async (event) => {
await runImportantTask();
}
);
Key Takeaway
Scheduled functions run server code on a timer without user involvement. Use App Engine cron syntax for simple human-readable schedules and Unix cron expressions for precise timing. Always specify a timezone for time-sensitive tasks. Use scheduled functions for daily cleanups, weekly reports, trial expiry checks, and any other recurring background tasks your app needs.
