Implementing Scheduled Notifications in Mobile Apps

Scheduled notifications — one of those tasks that seems simple until you hit platform limitations. On iOS — a limit of 64 active notifications, on Android — risk of reminders being lost after reboot. We've been building such systems for 7 years and know how to work around these pitfalls. In this art

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Implementing Scheduled Notifications in Mobile Apps
Simple
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Scheduled notifications — one of those tasks that seems simple until you hit platform limitations. On iOS — a limit of 64 active notifications, on Android — risk of reminders being lost after reboot. We've been building such systems for 7 years and know how to work around these pitfalls. In this article, we'll break down which technologies to choose and how to avoid typical mistakes.

Once a client asked to add daily reminders to a habit tracker. On the surface — a trivial task. But during testing on iOS, the app quickly hit the 64 notification limit, and on Android reminders stopped working after device reboot. We had to redesign the architecture: on iOS — dynamic identifier reuse, on Android — switching from AlarmManager to WorkManager. The experience cost a few sleepless nights, but the system became stable in the end.

When to choose what

Local notifications — if the time is tied to the user's device and doesn't change from the server. Habit tracker, medication reminder, event alarm.

Server-side scheduled — if centralized logic is needed: marketing campaigns by schedule, reminder about an event for all participants, deadline notification with user time zone consideration.

Local Server-side
Network dependency Not needed Needed
Management On device On backend
Max notifications 64 (iOS) / unlimited (Android) Unlimited
Recurrence Calendar/time triggers Cron / task queue
Example Reminder "stand up" every day at 9:00 Campaign "offer ends in an hour" to all users

How to choose between local and server-side notifications?

If the notification is tied to a user action (e.g., they set the reminder themselves) — go local. If the notification is server-initiated (new order, deadline, mass campaign) — go server-side. Hybrid approach: a local notification can be "synced" with the server via a push stub.

Server-side scheduling

OneSignal supports scheduled delivery directly in the API:

{ "app_id": "YOUR_APP_ID", "include_aliases": { "external_id": ["user_44521"] }, "contents": { "en": "Team meeting in 15 minutes" }, "send_after": "YYYY-MM-DD HH:MM:SS UTC", "delayed_option": "timezone", "delivery_time_of_day": "9:00AM" } 

delayed_option: "timezone" — deliver at the specified time of day considering each recipient's time zone. Useful for "good morning" campaigns.

For custom backend — cron job or task queue via Celery/BullMQ:

// Node.js + BullMQ const notificationQueue = new Queue('notifications', { connection: redis }); async function scheduleNotification(userId, content, sendAt) { const delay = sendAt.getTime() - Date.now(); await notificationQueue.add( 'send_push', { userId, content }, { delay, attempts: 3, backoff: { type: 'exponential', delay: 5000 } } ); } 

attempts: 3 with exponential backoff — a must. FCM sometimes returns 503, need retry.

Local scheduling on iOS

// Reminder every day at 8:00 func scheduleHabitReminder(habitId: String, name: String) { let content = UNMutableNotificationContent() content.title = name content.body = "Don't forget to mark completion" content.sound = .default content.userInfo = ["habit_id": habitId] var components = DateComponents() components.hour = 8 components.minute = 0 let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true) let request = UNNotificationRequest( identifier: "habit-\(habitId)", content: content, trigger: trigger ) UNUserNotificationCenter.current().add(request) { error in if let error { print("Schedule failed: \(error)") } } } // Change reminder time (remove old, add new) func rescheduleReminder(habitId: String, newHour: Int, newMinute: Int) { UNUserNotificationCenter.current() .removePendingNotificationRequests(withIdentifiers: ["habit-\(habitId)"]) // ... create new request with updated components } 

Apple recommends not exceeding 64 scheduled notifications per app (UNUserNotificationCenter).

Why WorkManager is preferable to AlarmManager on Android?

AlarmManager is precise but doesn't survive reboot. WorkManager survives reboot but execution time is approximate (±15 minutes on Android 12+ due to Doze). Choice depends on precision requirements. For reminders where precision isn't critical (e.g., "drink water"), WorkManager is a reliable solution.

// WorkManager — for non‑critical time reminders fun scheduleHabitReminder(habitId: String, reminderHour: Int, reminderMinute: Int) { // Calculate delay until next firing val now = Calendar.getInstance() val target = Calendar.getInstance().apply { set(Calendar.HOUR_OF_DAY, reminderHour) set(Calendar.MINUTE, reminderMinute) set(Calendar.SECOND, 0) if (before(now)) add(Calendar.DAY_OF_YEAR, 1) } val delayMs = target.timeInMillis - now.timeInMillis val workRequest = OneTimeWorkRequestBuilder<ReminderWorker>() .setInitialDelay(delayMs, TimeUnit.MILLISECONDS) .setInputData(workDataOf( "habit_id" to habitId, "next_reminder_hour" to reminderHour, "next_reminder_minute" to reminderMinute )) .build() WorkManager.getInstance(context) .enqueueUniqueWork("habit-$habitId", ExistingWorkPolicy.REPLACE, workRequest) } // In Worker — show notification and schedule next class ReminderWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { val habitId = inputData.getString("habit_id") ?: return Result.failure() showNotification(habitId) // Schedule next day scheduleHabitReminder( habitId, inputData.getInt("next_reminder_hour", 8), inputData.getInt("next_reminder_minute", 0) ) return Result.success() } } 

ExistingWorkPolicy.REPLACE — if user changes reminder time, old task is replaced with new one.

Managing reminders in UI

The user should see scheduled reminders and be able to manage them. On iOS:

// Load all pending reminders func loadPendingReminders() async -> [ScheduledReminder] { return await withCheckedContinuation { continuation in UNUserNotificationCenter.current().getPendingNotificationRequests { requests in let reminders = requests.compactMap { ScheduledReminder(from: $0) } continuation.resume(returning: reminders) } } } 

Display in a list with ability to edit time or delete. On delete — removePendingNotificationRequests + remove from WorkManager (Android).

Typical mistakes and how to avoid them

Checklist: what to check before deployment
  • Ensure iOS does not exceed 64 notification limit. Reuse identifiers.
  • On Android, test after device reboot.
  • For repeating notifications, use WorkManager with rescheduling inside Worker.
  • Test in Doze mode (Android) and Low Power Mode (iOS).
  • Ensure time zone is handled correctly.

What the work includes

Turnkey development of scheduled notifications includes:

  • Notification architecture design (local/server/hybrid)
  • Scheduler implementation on iOS (UNUserNotificationCenter) and Android (WorkManager or AlarmManager)
  • Server queue integration (BullMQ, Celery) or OneSignal
  • UI for schedule management (list, add, edit, delete)
  • Testing on real devices: Doze mode, reboot, time zone change
  • Documentation on access and operation

We guarantee stable notification operation — proven on 50+ projects. The cost of turnkey development depends on complexity and is determined after analysis. Contact us to pinpoint your case and get an estimate.

Timeline

Implementation of scheduled notifications with UI schedule management, reboot support on Android, and 64‑notification limit handling on iOS — 3–5 working days. If server-side scheduling via OneSignal or custom queue is added — another 2–3 days. Get a consultation and accurate estimate for your project — reach out to us.