APNs vs FCM untuk notifikasi push iOS dan Android
Perbandingan APNs dan FCM untuk iOS dan Android: siklus hidup token, batas payload, ekspektasi pengiriman, dan checklist praktis untuk memperbaiki notifikasi yang hilang.

What you are comparing (and why it matters)
APNs (Apple Push Notification service) dan FCM (Firebase Cloud Messaging) adalah jalur pengiriman yang memindahkan pesan dari server Anda ke ponsel. Mereka tidak menentukan apa yang dilakukan aplikasi Anda dengan pesan itu, tetapi sangat mempengaruhi apakah pesan sampai, seberapa cepat sampai, dan dalam bentuk apa pesan itu harus dikirim.
Saat orang bilang notifikasi push “berfungsi di Android tapi tidak di iOS” (atau sebaliknya), jarang itu karena satu bug tunggal. iOS dan Android menangani pekerjaan background, penghematan daya, izin, dan prioritas pesan secara berbeda. Pesan yang sama bisa tertunda, digantikan oleh yang lebih baru, muncul tanpa suara, atau tidak pernah ditampilkan jika aplikasi tidak bisa dibangunkan untuk memprosesnya.
Perbandingan ini berfokus pada bagian-bagian yang menyebabkan kejutan nyata dalam dunia nyata: bagaimana token perangkat berubah seiring waktu, seberapa besar payload Anda boleh, bagaimana strukturnya, apa ekspektasi pengiriman yang realistis, dan alasan umum mengapa notifikasi tampak hilang.
Ini tidak membahas memilih UI penyedia push, strategi marketing, atau membangun pipeline analytics penuh. Tujuannya di sini adalah keandalan dan debugging yang lebih cepat.
Beberapa istilah yang dipakai sepanjang artikel:
- Token: alamat spesifik perangkat yang Anda kirim, diterbitkan oleh APNs atau FCM.
- Topic: alamat grup (utama dipakai di FCM) tempat banyak perangkat berlangganan.
- Channel: kategori notifikasi Android yang mengontrol suara, pentingnya, dan perilaku.
- Collapse key: cara untuk mengganti pesan lama yang belum tersampaikan dengan yang lebih baru.
- TTL (time to live): berapa lama pesan dapat menunggu pengiriman sebelum kedaluwarsa.
Menguasai dasar ini menghemat jam tebakan saat "push sederhana" berperilaku berbeda antar iOS dan Android.
How APNs and FCM work at a high level
APNs dan FCM sama-sama perantara antara server Anda dan ponsel pengguna. Aplikasi Anda tidak bisa mengirim notifikasi push langsung dan dapat diandalkan ke perangkat lewat internet, jadi tugas itu diserahkan ke Apple (APNs) atau Google (FCM), yang sudah memelihara koneksi tepercaya ke perangkat mereka.
Alur keseluruhan serupa: aplikasi Anda mendapat token, backend Anda mengirim pesan ke layanan push menggunakan token itu, dan layanan push meneruskannya ke perangkat.
APNs in plain terms
Di iOS, aplikasi mendaftar untuk remote notifications dan (biasanya) meminta izin pengguna. Apple kemudian memberikan device token. Backend Anda (sering disebut “provider”) mengirim permintaan push ke APNs yang mencakup token itu dan payload Anda. APNs memutuskan apakah bisa mengirimkan dan meneruskan notifikasi ke perangkat.
Backend Anda mengautentikasi ke APNs, umumnya menggunakan token-based auth (kunci penandatanganan). Setup lama menggunakan sertifikat.
FCM in plain terms
Di Android, instance aplikasi mendaftar ke FCM dan menerima registration token. Backend Anda mengirim pesan ke FCM, dan FCM meneruskannya ke perangkat yang benar. Bergantung pada status aplikasi dan jenis pesan, FCM dapat menampilkan notifikasi secara otomatis atau menyampaikan data ke aplikasi untuk ditangani.
Backend Anda mengautentikasi ke FCM menggunakan kredensial server (API key atau service account).
Yang Anda kontrol: kode aplikasi, kapan meminta izin, penyimpanan token, logika backend, dan payload yang Anda kirim. Yang dikontrol Apple dan Google: jaringan pengiriman, reachability, aturan throttling, dan banyak kondisi last-mile seperti penghematan daya dan kebijakan sistem.
Token lifecycle: how tokens are issued, refreshed, and invalidated
Perbedaan terbesar sehari-hari antara APNs vs FCM adalah token bukanlah “sekali di-set dan selamanya.” Perlakukan mereka seperti alamat yang bisa berubah tanpa peringatan.
Di iOS, device token APNs terikat ke perangkat, aplikasi Anda, dan pengaturan developer Apple Anda. Token bisa berubah setelah reinstall aplikasi, restore perangkat, beberapa pembaruan OS, atau saat berpindah environment push (sandbox vs production) selama pengembangan.
Di Android, registration token FCM bisa refresh saat aplikasi dipulihkan pada perangkat baru, pengguna menghapus data aplikasi, Google merotasi token, atau aplikasi di-reinstall. Aplikasi Anda harus mengantisipasi event refresh dan segera mengirim token baru ke server Anda.
Aturan sederhana: selalu upsert token, jangan "insert and forget." Saat menyimpan token, simpan konteks yang cukup untuk menghindari duplikat dan target salah:
- User atau account ID (jika relevan)
- Bundle/package aplikasi dan environment
- Platform (iOS/Android)
- Nilai token dan timestamp last-seen
- Status opt-in (izin diberikan/ditolak)
Hapus juga penting. Anda biasanya tahu token mati dari error pengiriman, bukan dari sinyal "uninstall" yang bersih. Jika APNs mengembalikan error seperti Unregistered (sering dengan status 410), atau FCM mengatakan NotRegistered/Unregistered, hapus token itu segera agar Anda berhenti mencoba selamanya.
Satu kebocoran yang mudah terjadi: pelanggan logout dan orang lain login di telepon yang sama. Jika Anda tidak membersihkan atau memetakan ulang token saat logout, Anda bisa mengirim notifikasi ke orang yang salah walau pengiriman "berfungsi."
Payload constraints and message structure differences
Perbedaan praktis terbesar antara APNs vs FCM adalah apa yang muat dalam pesan dan bagaimana ponsel memperlakukannya saat tiba.
Kebanyakan tim mengandalkan beberapa field kecil:
- Judul dan teks body
- Badge count (iOS)
- Suara (default atau kustom)
- Data kunci-nilai kustom (mis.
order_id,status)
Size limits: keep the push small
Kedua layanan punya batas ukuran payload, dan batas itu termasuk data kustom Anda. Saat Anda mencapai batas, pengiriman bisa gagal atau pesan tidak berperilaku sebagaimana mestinya.
Polanya yang andal adalah mengirim notifikasi singkat plus sebuah ID, lalu ambil detail dari backend Anda:
Contoh: alih-alih mengirim ringkasan pesanan penuh, kirim { "type": "order_update", "order_id": "123" } dan biarkan aplikasi memanggil API Anda untuk memuat status terbaru.
Data-only vs notification behavior
Di Android, pesan FCM dengan payload "notification" biasanya ditampilkan oleh sistem saat aplikasi berada di background. Pesan data-only diserahkan ke kode aplikasi Anda, tetapi dapat tertunda atau diblokir oleh batasan background dan pengaturan baterai.
Di iOS, alert (title/body) sederhana, tetapi pembaruan background lebih ketat. Push background bukan jaminan bahwa kode Anda akan berjalan segera. Anggap itu sebagai petunjuk untuk refresh, bukan pemicu pekerjaan real-time.
Jika Anda membutuhkan keandalan, jaga payload minimal, sertakan identifier stabil, dan rancang aplikasi untuk merekonsiliasi state saat dibuka atau dilanjutkan.
Delivery expectations and what can stop a notification
Baik APNs maupun FCM bersifat best-effort. Provider akan mencoba mengirim pesan, tetapi tidak menjamin perangkat akan menampilkannya.
Reachability adalah pembatas pertama. Anda mengirim notifikasi dengan time-to-live (TTL) atau expiry. Jika perangkat kembali online setelah jendela itu, push akan di-drop. Jika TTL sangat panjang, pengguna mungkin melihat alert lama nanti, yang terlihat seperti bug.
Prioritas memengaruhi timing, tapi bukan upgrade gratis. Prioritas tinggi dapat membantu pesan sensitif-waktu tiba lebih cepat, terutama saat perangkat tidur. Menggunakannya berlebihan bisa menyebabkan throttling, baterai cepat habis, atau OS memperlakukan aplikasi Anda sebagai pengganggu.
Kedua sistem mendukung collapsing sehingga pesan lebih baru menggantikan yang lebih lama alih-alih menumpuk. APNs menggunakan collapse identifier, dan FCM menggunakan collapse key. Jika Anda collapse pada sesuatu seperti order_status, pengguna mungkin hanya melihat status terbaru, bukan setiap langkah.
Bahkan saat provider berhasil mengirim, ponsel masih bisa mencegah pengguna melihatnya:
- Do Not Disturb atau Focus modes dapat membisukan atau menyembunyikan alert
- Pengaturan notifikasi aplikasi bisa dimatikan atau disetel ke delivery senyap
- Channel notifikasi Android bisa dimatikan untuk kategori tertentu
- Pembatasan background atau penghemat baterai dapat menunda pengiriman
- OS dapat menekan pengulangan jika aplikasi Anda memposting banyak alert serupa
Perlakukan push sebagai transport yang tidak andal: simpan state penting di backend, dan buat aplikasi menyegarkan status saat dibuka, walau notifikasi tidak pernah muncul.
Permissions and device settings that affect delivery
Banyak "masalah pengiriman" sebenarnya adalah masalah izin dan pengaturan.
Di iOS, prompt izin pertama penting. Jika pengguna memilih "Don’t Allow," notifikasi tidak akan muncul sampai mereka mengubahnya di Settings. Bahkan setelah mengizinkan, mereka bisa mematikan Lock Screen, Notification Center, banner, suara, atau badge. Focus modes dan Scheduled Summary juga bisa menyembunyikan atau menunda alert.
Di Android, persyaratan bergantung versi OS. Versi terbaru mengharuskan izin notifikasi runtime, jadi pembaruan aplikasi bisa tiba-tiba menghentikan tampilan notifikasi sampai pengguna menyetujui lagi. Visibilitas juga bergantung pada notification channel. Jika channel dibisukan atau disetel ke importance rendah, push mungkin tiba tetapi tidak mengganggu.
Pembatasan background juga bisa mematahkan ekspektasi. Low Power Mode di iOS dan optimasi baterai di Android dapat menunda pekerjaan background, menghentikan data background, atau mencegah aplikasi memproses pesan data-only.
Untuk mengonfirmasi apa yang terjadi, catat apa yang dilihat perangkat, bukan hanya apa yang dikirim backend:
- Log dalam aplikasi: “permission granted,” “token registered,” “notification received,” “notification displayed”
- Indikator OS: status pengaturan notifikasi (enabled/muted/channel importance) dan mode baterai
- Callback push: apakah aplikasi menerima pesan di foreground/background
Bahkan jika backend Anda dibangun dengan tool no-code, logging sisi klien tetap memisahkan “pesan tidak diterima” dari “diterima tapi disembunyikan.”
Step-by-step: how to troubleshoot missing notifications
Saat push hilang, perlakukan seperti rantai: token, provider, payload, dan perilaku aplikasi. Gejala bisa terlihat sama di iOS dan Android, jadi periksa beberapa poin yang sama berurutan.
- Konfirmasi Anda mengirim ke token yang up-to-date. Bandingkan token yang tersimpan di server Anda dengan token yang terakhir dilaporkan aplikasi. Catat kapan terakhir menerima tiap token.
- Validasi payload sebelum dikirim. Jaga agar di bawah batas platform, gunakan field yang diperlukan, dan hindari JSON rusak. Jika Anda mengirim pesan data-only, pastikan aplikasi disusun untuk menanganinya.
- Periksa kredensial provider dan environment. Untuk APNs, pastikan key/cert, team, bundle ID, dan apakah Anda menarget sandbox vs production. Untuk FCM, pastikan kredensial project yang benar.
Lalu persempit apakah masalahnya pada konten pesan atau perilaku perangkat/aplikasi:
- Kirim notifikasi tes minimal. Payload judul/body kecil membantu memastikan transport bekerja.
- Verifikasi handler sisi aplikasi dan perilaku foreground. Banyak "push hilang" sebenarnya diterima tapi tidak ditampilkan. Beberapa aplikasi menonaktifkan banner saat foreground secara bawaan.
- Ubah satu variabel pada satu waktu. Coba perangkat kedua, versi OS berbeda, Wi‑Fi vs seluler, dan akun pengguna berbeda. Jika hanya satu akun gagal, biasanya menunjuk ke token usang atau penargetan server-side.
Polanya yang praktis: jika pengguna iOS melaporkan kehilangan tapi Android baik-baik saja, mulailah dengan mengirim alert minimal pada iOS. Jika itu berhasil, fokus ke struktur payload dan penanganan aplikasi. Jika tidak, fokus ke token dan kredensial/ environment APNs.
Common mistakes that cause silent failures
Kebanyakan masalah push bukan outage. Mereka mismatch kecil antara ekspektasi aplikasi Anda dan apa yang APNs atau FCM terima atau apa yang ponsel izinkan.
Kesalahan paling umum adalah mengirim ke token yang tidak lagi valid. Token berubah setelah reinstall, restore, atau refresh. Jika server terus menggunakan nilai lama, push pergi ke mana-mana.
Kesalahan lain adalah memperlakukan pengiriman push sebagai jaminan. Pengiriman best-effort berarti pesan terlambat atau hilang normal terjadi saat perangkat offline atau di bawah aturan penghematan daya. Untuk event penting (update pesanan, alert keamanan), Anda butuh fallback dalam aplikasi seperti mengambil status terbaru saat dibuka.
Penyebab umum notifikasi hilang:
- Token iOS atau Android yang usang tetap dipakai setelah reinstall/refresh
- Melebihi batas payload notifikasi (terlalu banyak data kustom, gambar besar, string panjang)
- Mengandalkan delivery background untuk update silent, lalu terkena throttling oleh batasan OS
- Mencampur environment iOS (development vs production), sehingga token dan endpoint APNs tidak cocok
- Mengabaikan opt-out pengguna, Focus/Do Not Disturb, channel notifikasi yang dimatikan (Android), atau izin notifikasi aplikasi
Contoh: sebuah app retail mengirim alert “order shipped” dengan JSON besar berisi histori tracking. Panggilan pengiriman terlihat sukses, tapi payload ditolak atau terpotong, dan pengguna tidak melihat apa-apa. Jaga push tetap kecil dan letakkan detail di balik panggilan API.
Quick checklist before you blame APNs or FCM
Sebelum menyalahkan provider, jalankan pengecekan dasar:
- Konfirmasi token benar untuk pengguna dan perangkat. Harus ada, diperbarui baru-baru ini, dan dipetakan ke sesi yang benar.
- Verifikasi kredensial provider valid saat ini. Periksa APNs keys/certs dan kredensial FCM cocok dengan aplikasi/project yang benar.
- Validasi bentuk dan ukuran payload. Tetap di bawah batas dan gunakan field yang benar.
- Atur TTL, priority, dan collapse dengan sengaja. TTL rendah bisa kedaluwarsa sebelum ponsel online. Prioritas rendah bisa menunda pengiriman. Collapse bisa menggantikan pesan lebih awal.
- Pisahkan “server accepted” dari “device displayed.” Bandingkan log server (request/response/message ID) dengan log klien (token digunakan, handler terpanggil).
Lalu lakukan cek cepat di perangkat: notifikasi diizinkan untuk aplikasi, channel/kategori yang benar dikonfigurasi (channel Android sering jadi jebakan), Focus/Do Not Disturb, dan pembatasan background.
Example: diagnosing a missing order update notification
Seorang agen support menekan “Send order update” untuk Order #1842. Log backend menunjukkan “notification sent,” tapi pelanggan tak melihat apa-apa di iPhone atau Android mereka.
Mulai di backend. Kebanyakan notifikasi “hilang” entah tidak diterima oleh layanan push, atau diterima tapi di-drop karena perangkat tidak bisa (atau tidak mau) menampilkannya.
Backend checks first
Cari satu upaya kirim yang dapat ditelusuri (satu update order harus menghasilkan satu permintaan push). Lalu verifikasi:
- Token yang digunakan adalah token terbaru yang tersimpan untuk pengguna dan perangkat itu.
- Respons provider menunjukkan sukses, dan Anda menyimpan kode error jika ada.
- Payload sesuai aturan platform (batas ukuran, field yang benar, JSON valid).
- Autentikasi valid (APNs key/cert dan team/bundle IDs, atau kredensial FCM).
- Anda menarget environment iOS yang benar (sandbox vs production).
Jika log menunjukkan penolakan seperti “unregistered/invalid token,” itu masalah lifecycle token. Jika provider menerima pesan tapi tidak ada yang tiba, fokus ke tipe payload dan perilaku OS.
Checks on the phone
Sekarang validasi apakah ponsel diizinkan menampilkan alert:
- Notifikasi diaktifkan untuk aplikasi (dan diizinkan untuk Lock Screen/Banners).
- Focus/Do Not Disturb atau scheduled summaries tidak menyembunyikannya.
- Mode penghemat baterai tidak membatasi pekerjaan background (lebih sering di Android).
- Status aplikasi sesuai dengan jenis pesan Anda (penanganan foreground bisa menelan alert).
Hasil umum: token baik, tapi pesan data-only (Android) atau pengaturan iOS untuk background tidak lengkap, sehingga OS tidak pernah menampilkan alert. Perbaikannya adalah mengirim jenis payload yang tepat untuk tujuan Anda (alert terlihat vs update background) dan simpan log bersih dari pembaruan token dan respons provider.
Next steps: make push more reliable in your product
Notifikasi push terasa sederhana sampai menjadi fitur inti. Keandalan datang dari bagian yang Anda kontrol: kebersihan token, disiplin payload, dan jalur fallback.
Rencanakan untuk kehilangan notifikasi. Push bagus untuk momen "lihat sekarang", tapi tidak boleh menjadi satu-satunya jalur untuk event kritis. Inbox dalam aplikasi membantu pengguna mengejar ketinggalan nanti, dan email atau SMS dapat menutup event bernilai tinggi seperti reset password atau masalah pembayaran.
Jaga payload ramping. Perlakukan payload push sebagai prompt, bukan pesan penuh. Kirim tipe event dan ID, lalu ambil detail dari API backend saat aplikasi dibuka atau menerima background update yang sesuai.
Tulis runbook singkat untuk tim Anda supaya debugging konsisten: status opt-in, kesegaran token, kode respons provider, ukuran/bentuk payload, dan environment/kredensial.
Jika Anda membangun dengan AppMaster (appmaster.io), berguna untuk menyimpan tabel token, log audit, dan logika pemicu push di satu backend, sambil tetap mengirim aplikasi native iOS dan Android yang menangani APNs dan FCM dengan benar.
FAQ
APNs adalah layanan pengiriman Apple untuk notifikasi push iOS, dan FCM adalah layanan pengiriman Google untuk Android (dan juga dapat menarget iOS lewat APNs). Aplikasi Anda tetap menentukan apa yang dilakukan terhadap pesan, tetapi layanan ini menentukan cara autentikasi, format payload, dan perilaku pengiriman yang dapat Anda harapkan.
Perlakukan token sebagai alamat yang bisa berubah. Simpan bersama detail platform dan environment, perbarui saat aplikasi melaporkan nilai baru, dan hapus saat provider memberi tahu token tidak valid. Aturan praktisnya adalah upsert token dan simpan timestamp “last seen” sehingga Anda cepat menemukan data usang.
Di iOS, token sering berubah setelah reinstall, restore perangkat, beberapa pembaruan OS, atau saat berpindah antara sandbox dan production saat pengembangan. Di Android, token FCM dapat diperbarui setelah reinstall, saat pengguna membersihkan data aplikasi, saat perangkat dipulihkan, atau ketika Google merotasi token. Aplikasi Anda harus mendengarkan event refresh dan segera mengirim token baru ke backend.
Jaga payload notifikasi tetap kecil dan perlakukan push sebagai pemicu. Kirim judul/body pendek (jika perlu tampilan terlihat) plus identifier stabil seperti order_id, lalu biarkan aplikasi mengambil detail penuh dari API Anda. Ini menghindari batas ukuran payload, mengurangi kasus edge, dan membuat perilaku lebih konsisten antar platform.
Payload tipe notification dimaksudkan untuk ditampilkan ke pengguna, sedangkan payload data-only dimaksudkan untuk diproses aplikasi. Di Android, pesan data-only bisa tertunda atau diblokir oleh batasan background dan pengaturan baterai, jadi bukan trigger yang andal untuk kerja langsung. Di iOS, push background juga tidak menjamin kode Anda berjalan segera—anggap itu sebagai petunjuk untuk melakukan refresh, bukan eksekusi pekerjaan waktu-nyata.
Tidak, pengiriman bersifat best-effort. Bahkan jika APNs atau FCM menerima permintaan Anda, perangkat mungkin offline, pesan bisa kadaluwarsa karena TTL, OS dapat menunda pengiriman, atau pengaturan pengguna bisa menekan notifikasi. Rancang aplikasi sehingga state penting selalu benar saat pengguna membuka aplikasi, walau notifikasi tidak pernah muncul.
Pisahkan antara “terkirim” dan “ditampilkan.” Konfirmasi token masih valid, kirim payload tes title/body minimal, dan verifikasi kredensial APNs/FCM yang benar dan (untuk iOS) lingkungan yang tepat. Jika provider menerima pesan, periksa pengaturan telepon seperti Focus/Do Not Disturb, izin notifikasi aplikasi, dan channel notifikasi Android—karena seringkali notifikasi diterima tapi disembunyikan.
Di iOS, masalah sering dari penolakan izin, Focus modes, atau menargetkan environment APNs yang salah (sandbox vs production). Di Android, penghalang umum adalah izin notifikasi runtime pada versi OS baru, channel yang dibisukan/berkepentingan rendah, dan optimasi baterai agresif yang menunda pemrosesan background. Satu pengiriman backend bisa terlihat normal sementara perangkat mencegah tampilan ke pengguna.
TTL mengontrol berapa lama provider harus terus mencoba saat perangkat offline, dan pengaturan collapse menentukan apakah pesan baru menggantikan yang lebih lama. TTL pendek bisa membuat notifikasi hilang jika ponsel offline cukup lama, dan collapse key/identifier bisa membuat hanya pembaruan terbaru yang terlihat. Atur nilai-nilai ini dengan sengaja sesuai pengalaman pengguna yang Anda inginkan.
Simpan penyimpanan token, aturan penargetan, dan log pengiriman bersama sehingga Anda bisa menelusuri setiap upaya push dari ujung ke ujung. AppMaster dapat membantu dengan memusatkan tabel token, log audit, dan logika pemicu push di satu backend, sementara aplikasi native iOS dan Android masih menangani APNs dan FCM dengan benar. Kuncinya adalah mencatat pembaruan token, respons provider, dan penerimaan sisi klien supaya Anda bisa menentukan apakah kegagalan pada server, provider, atau perangkat.


