@wazir-dev/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (629) hide show
  1. package/AGENTS.md +111 -0
  2. package/CHANGELOG.md +14 -0
  3. package/CONTRIBUTING.md +101 -0
  4. package/LICENSE +21 -0
  5. package/README.md +314 -0
  6. package/assets/composition-engine.mmd +34 -0
  7. package/assets/demo-script.sh +17 -0
  8. package/assets/logo-dark.svg +14 -0
  9. package/assets/logo.svg +14 -0
  10. package/assets/pipeline.mmd +39 -0
  11. package/assets/record-demo.sh +51 -0
  12. package/docs/README.md +51 -0
  13. package/docs/adapters/context-mode.md +60 -0
  14. package/docs/concepts/architecture.md +87 -0
  15. package/docs/concepts/artifact-model.md +60 -0
  16. package/docs/concepts/composition-engine.md +36 -0
  17. package/docs/concepts/indexing-and-recall.md +160 -0
  18. package/docs/concepts/observability.md +41 -0
  19. package/docs/concepts/roles-and-workflows.md +59 -0
  20. package/docs/concepts/terminology-policy.md +27 -0
  21. package/docs/getting-started/01-installation.md +78 -0
  22. package/docs/getting-started/02-first-run.md +102 -0
  23. package/docs/getting-started/03-adding-to-project.md +15 -0
  24. package/docs/getting-started/04-host-setup.md +15 -0
  25. package/docs/guides/ci-integration.md +15 -0
  26. package/docs/guides/creating-skills.md +15 -0
  27. package/docs/guides/expertise-module-authoring.md +15 -0
  28. package/docs/guides/hook-development.md +15 -0
  29. package/docs/guides/memory-and-learnings.md +34 -0
  30. package/docs/guides/multi-host-export.md +15 -0
  31. package/docs/guides/troubleshooting.md +101 -0
  32. package/docs/guides/writing-custom-roles.md +15 -0
  33. package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
  34. package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
  35. package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
  36. package/docs/readmes/INDEX.md +99 -0
  37. package/docs/readmes/features/expertise/README.md +171 -0
  38. package/docs/readmes/features/exports/README.md +222 -0
  39. package/docs/readmes/features/hooks/README.md +103 -0
  40. package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
  41. package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
  42. package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
  43. package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
  44. package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
  45. package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
  46. package/docs/readmes/features/hooks/session-start.md +119 -0
  47. package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
  48. package/docs/readmes/features/roles/README.md +157 -0
  49. package/docs/readmes/features/roles/clarifier.md +152 -0
  50. package/docs/readmes/features/roles/content-author.md +190 -0
  51. package/docs/readmes/features/roles/designer.md +193 -0
  52. package/docs/readmes/features/roles/executor.md +184 -0
  53. package/docs/readmes/features/roles/learner.md +210 -0
  54. package/docs/readmes/features/roles/planner.md +182 -0
  55. package/docs/readmes/features/roles/researcher.md +164 -0
  56. package/docs/readmes/features/roles/reviewer.md +184 -0
  57. package/docs/readmes/features/roles/specifier.md +162 -0
  58. package/docs/readmes/features/roles/verifier.md +215 -0
  59. package/docs/readmes/features/schemas/README.md +178 -0
  60. package/docs/readmes/features/skills/README.md +63 -0
  61. package/docs/readmes/features/skills/brainstorming.md +96 -0
  62. package/docs/readmes/features/skills/debugging.md +148 -0
  63. package/docs/readmes/features/skills/design.md +120 -0
  64. package/docs/readmes/features/skills/prepare-next.md +109 -0
  65. package/docs/readmes/features/skills/run-audit.md +159 -0
  66. package/docs/readmes/features/skills/scan-project.md +109 -0
  67. package/docs/readmes/features/skills/self-audit.md +176 -0
  68. package/docs/readmes/features/skills/tdd.md +137 -0
  69. package/docs/readmes/features/skills/using-skills.md +92 -0
  70. package/docs/readmes/features/skills/verification.md +120 -0
  71. package/docs/readmes/features/skills/writing-plans.md +104 -0
  72. package/docs/readmes/features/tooling/README.md +320 -0
  73. package/docs/readmes/features/workflows/README.md +186 -0
  74. package/docs/readmes/features/workflows/author.md +181 -0
  75. package/docs/readmes/features/workflows/clarify.md +154 -0
  76. package/docs/readmes/features/workflows/design-review.md +171 -0
  77. package/docs/readmes/features/workflows/design.md +169 -0
  78. package/docs/readmes/features/workflows/discover.md +162 -0
  79. package/docs/readmes/features/workflows/execute.md +173 -0
  80. package/docs/readmes/features/workflows/learn.md +167 -0
  81. package/docs/readmes/features/workflows/plan-review.md +165 -0
  82. package/docs/readmes/features/workflows/plan.md +170 -0
  83. package/docs/readmes/features/workflows/prepare-next.md +167 -0
  84. package/docs/readmes/features/workflows/review.md +169 -0
  85. package/docs/readmes/features/workflows/run-audit.md +191 -0
  86. package/docs/readmes/features/workflows/spec-challenge.md +159 -0
  87. package/docs/readmes/features/workflows/specify.md +160 -0
  88. package/docs/readmes/features/workflows/verify.md +177 -0
  89. package/docs/readmes/packages/README.md +50 -0
  90. package/docs/readmes/packages/ajv.md +117 -0
  91. package/docs/readmes/packages/context-mode.md +118 -0
  92. package/docs/readmes/packages/gray-matter.md +116 -0
  93. package/docs/readmes/packages/node-test.md +137 -0
  94. package/docs/readmes/packages/yaml.md +112 -0
  95. package/docs/reference/configuration-reference.md +159 -0
  96. package/docs/reference/expertise-index.md +52 -0
  97. package/docs/reference/git-flow.md +43 -0
  98. package/docs/reference/hooks.md +87 -0
  99. package/docs/reference/host-exports.md +50 -0
  100. package/docs/reference/launch-checklist.md +172 -0
  101. package/docs/reference/marketplace-listings.md +76 -0
  102. package/docs/reference/release-process.md +34 -0
  103. package/docs/reference/roles-reference.md +77 -0
  104. package/docs/reference/skills.md +33 -0
  105. package/docs/reference/templates.md +29 -0
  106. package/docs/reference/tooling-cli.md +94 -0
  107. package/docs/truth-claims.yaml +222 -0
  108. package/expertise/PROGRESS.md +63 -0
  109. package/expertise/README.md +18 -0
  110. package/expertise/antipatterns/PROGRESS.md +56 -0
  111. package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
  112. package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
  113. package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
  114. package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
  115. package/expertise/antipatterns/backend/index.md +24 -0
  116. package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
  117. package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
  118. package/expertise/antipatterns/code/async-antipatterns.md +622 -0
  119. package/expertise/antipatterns/code/code-smells.md +1186 -0
  120. package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
  121. package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
  122. package/expertise/antipatterns/code/index.md +27 -0
  123. package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
  124. package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
  125. package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
  126. package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
  127. package/expertise/antipatterns/design/dark-patterns.md +1121 -0
  128. package/expertise/antipatterns/design/index.md +22 -0
  129. package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
  130. package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
  131. package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
  132. package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
  133. package/expertise/antipatterns/frontend/index.md +23 -0
  134. package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
  135. package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
  136. package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
  137. package/expertise/antipatterns/index.md +31 -0
  138. package/expertise/antipatterns/performance/index.md +20 -0
  139. package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
  140. package/expertise/antipatterns/performance/premature-optimization.md +623 -0
  141. package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
  142. package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
  143. package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
  144. package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
  145. package/expertise/antipatterns/process/index.md +23 -0
  146. package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
  147. package/expertise/antipatterns/security/index.md +20 -0
  148. package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
  149. package/expertise/antipatterns/security/security-theater.md +843 -0
  150. package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
  151. package/expertise/architecture/PROGRESS.md +70 -0
  152. package/expertise/architecture/data/caching-architecture.md +671 -0
  153. package/expertise/architecture/data/data-consistency.md +574 -0
  154. package/expertise/architecture/data/data-modeling.md +536 -0
  155. package/expertise/architecture/data/event-streams-and-queues.md +634 -0
  156. package/expertise/architecture/data/index.md +25 -0
  157. package/expertise/architecture/data/search-architecture.md +663 -0
  158. package/expertise/architecture/data/sql-vs-nosql.md +708 -0
  159. package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
  160. package/expertise/architecture/decisions/build-vs-buy.md +616 -0
  161. package/expertise/architecture/decisions/index.md +23 -0
  162. package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
  163. package/expertise/architecture/decisions/technology-selection.md +616 -0
  164. package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
  165. package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
  166. package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
  167. package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
  168. package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
  169. package/expertise/architecture/distributed/index.md +25 -0
  170. package/expertise/architecture/distributed/saga-pattern.md +797 -0
  171. package/expertise/architecture/foundations/architectural-thinking.md +460 -0
  172. package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
  173. package/expertise/architecture/foundations/design-principles-solid.md +649 -0
  174. package/expertise/architecture/foundations/domain-driven-design.md +719 -0
  175. package/expertise/architecture/foundations/index.md +25 -0
  176. package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
  177. package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
  178. package/expertise/architecture/index.md +34 -0
  179. package/expertise/architecture/integration/api-design-graphql.md +638 -0
  180. package/expertise/architecture/integration/api-design-grpc.md +804 -0
  181. package/expertise/architecture/integration/api-design-rest.md +892 -0
  182. package/expertise/architecture/integration/index.md +25 -0
  183. package/expertise/architecture/integration/third-party-integration.md +795 -0
  184. package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
  185. package/expertise/architecture/integration/websockets-realtime.md +791 -0
  186. package/expertise/architecture/mobile-architecture/index.md +22 -0
  187. package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
  188. package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
  189. package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
  190. package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
  191. package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
  192. package/expertise/architecture/patterns/event-driven.md +797 -0
  193. package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
  194. package/expertise/architecture/patterns/index.md +27 -0
  195. package/expertise/architecture/patterns/layered-architecture.md +736 -0
  196. package/expertise/architecture/patterns/microservices.md +753 -0
  197. package/expertise/architecture/patterns/modular-monolith.md +692 -0
  198. package/expertise/architecture/patterns/monolith.md +626 -0
  199. package/expertise/architecture/patterns/plugin-architecture.md +735 -0
  200. package/expertise/architecture/patterns/serverless.md +780 -0
  201. package/expertise/architecture/scaling/database-scaling.md +615 -0
  202. package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
  203. package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
  204. package/expertise/architecture/scaling/index.md +24 -0
  205. package/expertise/architecture/scaling/multi-tenancy.md +800 -0
  206. package/expertise/architecture/scaling/stateless-design.md +787 -0
  207. package/expertise/backend/embedded-firmware.md +625 -0
  208. package/expertise/backend/go.md +853 -0
  209. package/expertise/backend/index.md +24 -0
  210. package/expertise/backend/java-spring.md +448 -0
  211. package/expertise/backend/node-typescript.md +625 -0
  212. package/expertise/backend/python-fastapi.md +724 -0
  213. package/expertise/backend/rust.md +458 -0
  214. package/expertise/backend/solidity.md +711 -0
  215. package/expertise/composition-map.yaml +443 -0
  216. package/expertise/content/foundations/content-modeling.md +395 -0
  217. package/expertise/content/foundations/editorial-standards.md +449 -0
  218. package/expertise/content/foundations/index.md +24 -0
  219. package/expertise/content/foundations/microcopy.md +455 -0
  220. package/expertise/content/foundations/terminology-governance.md +509 -0
  221. package/expertise/content/index.md +34 -0
  222. package/expertise/content/patterns/accessibility-copy.md +518 -0
  223. package/expertise/content/patterns/index.md +24 -0
  224. package/expertise/content/patterns/notification-content.md +433 -0
  225. package/expertise/content/patterns/sample-content.md +486 -0
  226. package/expertise/content/patterns/state-copy.md +439 -0
  227. package/expertise/design/PROGRESS.md +58 -0
  228. package/expertise/design/disciplines/dark-mode-theming.md +577 -0
  229. package/expertise/design/disciplines/design-systems.md +595 -0
  230. package/expertise/design/disciplines/index.md +25 -0
  231. package/expertise/design/disciplines/information-architecture.md +800 -0
  232. package/expertise/design/disciplines/interaction-design.md +788 -0
  233. package/expertise/design/disciplines/responsive-design.md +552 -0
  234. package/expertise/design/disciplines/usability-testing.md +516 -0
  235. package/expertise/design/disciplines/user-research.md +792 -0
  236. package/expertise/design/foundations/accessibility-design.md +796 -0
  237. package/expertise/design/foundations/color-theory.md +797 -0
  238. package/expertise/design/foundations/iconography.md +795 -0
  239. package/expertise/design/foundations/index.md +26 -0
  240. package/expertise/design/foundations/motion-and-animation.md +653 -0
  241. package/expertise/design/foundations/rtl-design.md +585 -0
  242. package/expertise/design/foundations/spacing-and-layout.md +607 -0
  243. package/expertise/design/foundations/typography.md +800 -0
  244. package/expertise/design/foundations/visual-hierarchy.md +761 -0
  245. package/expertise/design/index.md +32 -0
  246. package/expertise/design/patterns/authentication-flows.md +474 -0
  247. package/expertise/design/patterns/content-consumption.md +789 -0
  248. package/expertise/design/patterns/data-display.md +618 -0
  249. package/expertise/design/patterns/e-commerce.md +1494 -0
  250. package/expertise/design/patterns/feedback-and-states.md +642 -0
  251. package/expertise/design/patterns/forms-and-input.md +819 -0
  252. package/expertise/design/patterns/gamification.md +801 -0
  253. package/expertise/design/patterns/index.md +31 -0
  254. package/expertise/design/patterns/microinteractions.md +449 -0
  255. package/expertise/design/patterns/navigation.md +800 -0
  256. package/expertise/design/patterns/notifications.md +705 -0
  257. package/expertise/design/patterns/onboarding.md +700 -0
  258. package/expertise/design/patterns/search-and-filter.md +601 -0
  259. package/expertise/design/patterns/settings-and-preferences.md +768 -0
  260. package/expertise/design/patterns/social-and-community.md +748 -0
  261. package/expertise/design/platforms/desktop-native.md +612 -0
  262. package/expertise/design/platforms/index.md +25 -0
  263. package/expertise/design/platforms/mobile-android.md +825 -0
  264. package/expertise/design/platforms/mobile-cross-platform.md +983 -0
  265. package/expertise/design/platforms/mobile-ios.md +699 -0
  266. package/expertise/design/platforms/tablet.md +794 -0
  267. package/expertise/design/platforms/web-dashboard.md +790 -0
  268. package/expertise/design/platforms/web-responsive.md +550 -0
  269. package/expertise/design/psychology/behavioral-nudges.md +449 -0
  270. package/expertise/design/psychology/cognitive-load.md +1191 -0
  271. package/expertise/design/psychology/error-psychology.md +778 -0
  272. package/expertise/design/psychology/index.md +22 -0
  273. package/expertise/design/psychology/persuasive-design.md +736 -0
  274. package/expertise/design/psychology/user-mental-models.md +623 -0
  275. package/expertise/design/tooling/open-pencil.md +266 -0
  276. package/expertise/frontend/angular.md +1073 -0
  277. package/expertise/frontend/desktop-electron.md +546 -0
  278. package/expertise/frontend/flutter.md +782 -0
  279. package/expertise/frontend/index.md +27 -0
  280. package/expertise/frontend/native-android.md +409 -0
  281. package/expertise/frontend/native-ios.md +490 -0
  282. package/expertise/frontend/react-native.md +1160 -0
  283. package/expertise/frontend/react.md +808 -0
  284. package/expertise/frontend/vue.md +1089 -0
  285. package/expertise/humanize/domain-rules-code.md +79 -0
  286. package/expertise/humanize/domain-rules-content.md +67 -0
  287. package/expertise/humanize/domain-rules-technical-docs.md +56 -0
  288. package/expertise/humanize/index.md +35 -0
  289. package/expertise/humanize/self-audit-checklist.md +87 -0
  290. package/expertise/humanize/sentence-patterns.md +218 -0
  291. package/expertise/humanize/vocabulary-blacklist.md +105 -0
  292. package/expertise/i18n/PROGRESS.md +65 -0
  293. package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
  294. package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
  295. package/expertise/i18n/advanced/complex-scripts.md +30 -0
  296. package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
  297. package/expertise/i18n/advanced/testing-i18n.md +28 -0
  298. package/expertise/i18n/content/content-adaptation.md +23 -0
  299. package/expertise/i18n/content/locale-specific-formatting.md +23 -0
  300. package/expertise/i18n/content/machine-translation-integration.md +28 -0
  301. package/expertise/i18n/content/translation-management.md +29 -0
  302. package/expertise/i18n/foundations/date-time-calendars.md +67 -0
  303. package/expertise/i18n/foundations/i18n-architecture.md +272 -0
  304. package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
  305. package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
  306. package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
  307. package/expertise/i18n/foundations/string-externalization.md +236 -0
  308. package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
  309. package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
  310. package/expertise/i18n/index.md +38 -0
  311. package/expertise/i18n/platform/backend-i18n.md +31 -0
  312. package/expertise/i18n/platform/flutter-i18n.md +148 -0
  313. package/expertise/i18n/platform/native-android-i18n.md +36 -0
  314. package/expertise/i18n/platform/native-ios-i18n.md +36 -0
  315. package/expertise/i18n/platform/react-i18n.md +103 -0
  316. package/expertise/i18n/platform/web-css-i18n.md +81 -0
  317. package/expertise/i18n/rtl/arabic-specific.md +175 -0
  318. package/expertise/i18n/rtl/hebrew-specific.md +149 -0
  319. package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
  320. package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
  321. package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
  322. package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
  323. package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
  324. package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
  325. package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
  326. package/expertise/i18n/rtl/rtl-typography.md +160 -0
  327. package/expertise/index.md +113 -0
  328. package/expertise/index.yaml +216 -0
  329. package/expertise/infrastructure/cloud-aws.md +597 -0
  330. package/expertise/infrastructure/cloud-gcp.md +599 -0
  331. package/expertise/infrastructure/cybersecurity.md +816 -0
  332. package/expertise/infrastructure/database-mongodb.md +447 -0
  333. package/expertise/infrastructure/database-postgres.md +400 -0
  334. package/expertise/infrastructure/devops-cicd.md +787 -0
  335. package/expertise/infrastructure/index.md +27 -0
  336. package/expertise/performance/PROGRESS.md +50 -0
  337. package/expertise/performance/backend/api-latency.md +1204 -0
  338. package/expertise/performance/backend/background-jobs.md +506 -0
  339. package/expertise/performance/backend/connection-pooling.md +1209 -0
  340. package/expertise/performance/backend/database-query-optimization.md +515 -0
  341. package/expertise/performance/backend/index.md +23 -0
  342. package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
  343. package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
  344. package/expertise/performance/foundations/caching-strategies.md +489 -0
  345. package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
  346. package/expertise/performance/foundations/index.md +24 -0
  347. package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
  348. package/expertise/performance/foundations/memory-management.md +964 -0
  349. package/expertise/performance/foundations/performance-budgets.md +1314 -0
  350. package/expertise/performance/index.md +31 -0
  351. package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
  352. package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
  353. package/expertise/performance/infrastructure/index.md +22 -0
  354. package/expertise/performance/infrastructure/load-balancing.md +1081 -0
  355. package/expertise/performance/infrastructure/observability.md +1079 -0
  356. package/expertise/performance/mobile/index.md +23 -0
  357. package/expertise/performance/mobile/mobile-animations.md +544 -0
  358. package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
  359. package/expertise/performance/mobile/mobile-network.md +452 -0
  360. package/expertise/performance/mobile/mobile-rendering.md +599 -0
  361. package/expertise/performance/mobile/mobile-startup-time.md +505 -0
  362. package/expertise/performance/platform-specific/flutter-performance.md +647 -0
  363. package/expertise/performance/platform-specific/index.md +22 -0
  364. package/expertise/performance/platform-specific/node-performance.md +1307 -0
  365. package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
  366. package/expertise/performance/platform-specific/react-performance.md +1403 -0
  367. package/expertise/performance/web/bundle-optimization.md +1239 -0
  368. package/expertise/performance/web/image-and-media.md +636 -0
  369. package/expertise/performance/web/index.md +24 -0
  370. package/expertise/performance/web/network-optimization.md +1133 -0
  371. package/expertise/performance/web/rendering-performance.md +1098 -0
  372. package/expertise/performance/web/ssr-and-hydration.md +918 -0
  373. package/expertise/performance/web/web-vitals.md +1374 -0
  374. package/expertise/quality/accessibility.md +985 -0
  375. package/expertise/quality/evidence-based-verification.md +499 -0
  376. package/expertise/quality/index.md +24 -0
  377. package/expertise/quality/ml-model-audit.md +614 -0
  378. package/expertise/quality/performance.md +600 -0
  379. package/expertise/quality/testing-api.md +891 -0
  380. package/expertise/quality/testing-mobile.md +496 -0
  381. package/expertise/quality/testing-web.md +849 -0
  382. package/expertise/security/PROGRESS.md +54 -0
  383. package/expertise/security/agentic-identity.md +540 -0
  384. package/expertise/security/compliance-frameworks.md +601 -0
  385. package/expertise/security/data/data-encryption.md +364 -0
  386. package/expertise/security/data/data-privacy-gdpr.md +692 -0
  387. package/expertise/security/data/database-security.md +1171 -0
  388. package/expertise/security/data/index.md +22 -0
  389. package/expertise/security/data/pii-handling.md +531 -0
  390. package/expertise/security/foundations/authentication.md +1041 -0
  391. package/expertise/security/foundations/authorization.md +603 -0
  392. package/expertise/security/foundations/cryptography.md +1001 -0
  393. package/expertise/security/foundations/index.md +25 -0
  394. package/expertise/security/foundations/owasp-top-10.md +1354 -0
  395. package/expertise/security/foundations/secrets-management.md +1217 -0
  396. package/expertise/security/foundations/secure-sdlc.md +700 -0
  397. package/expertise/security/foundations/supply-chain-security.md +698 -0
  398. package/expertise/security/index.md +31 -0
  399. package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
  400. package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
  401. package/expertise/security/infrastructure/container-security.md +721 -0
  402. package/expertise/security/infrastructure/incident-response.md +1295 -0
  403. package/expertise/security/infrastructure/index.md +24 -0
  404. package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
  405. package/expertise/security/infrastructure/network-security.md +1337 -0
  406. package/expertise/security/mobile/index.md +23 -0
  407. package/expertise/security/mobile/mobile-android-security.md +1218 -0
  408. package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
  409. package/expertise/security/mobile/mobile-data-storage.md +1265 -0
  410. package/expertise/security/mobile/mobile-ios-security.md +1401 -0
  411. package/expertise/security/mobile/mobile-network-security.md +1520 -0
  412. package/expertise/security/smart-contract-security.md +594 -0
  413. package/expertise/security/testing/index.md +22 -0
  414. package/expertise/security/testing/penetration-testing.md +1258 -0
  415. package/expertise/security/testing/security-code-review.md +1765 -0
  416. package/expertise/security/testing/threat-modeling.md +1074 -0
  417. package/expertise/security/testing/vulnerability-scanning.md +1062 -0
  418. package/expertise/security/web/api-security.md +586 -0
  419. package/expertise/security/web/cors-and-headers.md +433 -0
  420. package/expertise/security/web/csrf.md +562 -0
  421. package/expertise/security/web/file-upload.md +1477 -0
  422. package/expertise/security/web/index.md +25 -0
  423. package/expertise/security/web/injection.md +1375 -0
  424. package/expertise/security/web/session-management.md +1101 -0
  425. package/expertise/security/web/xss.md +1158 -0
  426. package/exports/README.md +17 -0
  427. package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
  428. package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
  429. package/exports/hosts/claude/.claude/agents/designer.md +55 -0
  430. package/exports/hosts/claude/.claude/agents/executor.md +55 -0
  431. package/exports/hosts/claude/.claude/agents/learner.md +51 -0
  432. package/exports/hosts/claude/.claude/agents/planner.md +53 -0
  433. package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
  434. package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
  435. package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
  436. package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
  437. package/exports/hosts/claude/.claude/commands/author.md +42 -0
  438. package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
  439. package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
  440. package/exports/hosts/claude/.claude/commands/design.md +44 -0
  441. package/exports/hosts/claude/.claude/commands/discover.md +37 -0
  442. package/exports/hosts/claude/.claude/commands/execute.md +48 -0
  443. package/exports/hosts/claude/.claude/commands/learn.md +38 -0
  444. package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
  445. package/exports/hosts/claude/.claude/commands/plan.md +39 -0
  446. package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
  447. package/exports/hosts/claude/.claude/commands/review.md +40 -0
  448. package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
  449. package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
  450. package/exports/hosts/claude/.claude/commands/specify.md +38 -0
  451. package/exports/hosts/claude/.claude/commands/verify.md +37 -0
  452. package/exports/hosts/claude/.claude/settings.json +34 -0
  453. package/exports/hosts/claude/CLAUDE.md +19 -0
  454. package/exports/hosts/claude/export.manifest.json +38 -0
  455. package/exports/hosts/claude/host-package.json +67 -0
  456. package/exports/hosts/codex/AGENTS.md +19 -0
  457. package/exports/hosts/codex/export.manifest.json +38 -0
  458. package/exports/hosts/codex/host-package.json +41 -0
  459. package/exports/hosts/cursor/.cursor/hooks.json +16 -0
  460. package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
  461. package/exports/hosts/cursor/export.manifest.json +38 -0
  462. package/exports/hosts/cursor/host-package.json +42 -0
  463. package/exports/hosts/gemini/GEMINI.md +19 -0
  464. package/exports/hosts/gemini/export.manifest.json +38 -0
  465. package/exports/hosts/gemini/host-package.json +41 -0
  466. package/hooks/README.md +18 -0
  467. package/hooks/definitions/loop_cap_guard.yaml +21 -0
  468. package/hooks/definitions/post_tool_capture.yaml +24 -0
  469. package/hooks/definitions/pre_compact_summary.yaml +19 -0
  470. package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
  471. package/hooks/definitions/protected_path_write_guard.yaml +19 -0
  472. package/hooks/definitions/session_start.yaml +19 -0
  473. package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
  474. package/hooks/loop-cap-guard +17 -0
  475. package/hooks/post-tool-lint +36 -0
  476. package/hooks/protected-path-write-guard +17 -0
  477. package/hooks/session-start +41 -0
  478. package/llms-full.txt +2355 -0
  479. package/llms.txt +43 -0
  480. package/package.json +79 -0
  481. package/roles/README.md +20 -0
  482. package/roles/clarifier.md +42 -0
  483. package/roles/content-author.md +63 -0
  484. package/roles/designer.md +55 -0
  485. package/roles/executor.md +55 -0
  486. package/roles/learner.md +51 -0
  487. package/roles/planner.md +53 -0
  488. package/roles/researcher.md +43 -0
  489. package/roles/reviewer.md +54 -0
  490. package/roles/specifier.md +47 -0
  491. package/roles/verifier.md +71 -0
  492. package/schemas/README.md +24 -0
  493. package/schemas/accepted-learning.schema.json +20 -0
  494. package/schemas/author-artifact.schema.json +156 -0
  495. package/schemas/clarification.schema.json +19 -0
  496. package/schemas/design-artifact.schema.json +80 -0
  497. package/schemas/docs-claim.schema.json +18 -0
  498. package/schemas/export-manifest.schema.json +20 -0
  499. package/schemas/hook.schema.json +67 -0
  500. package/schemas/host-export-package.schema.json +18 -0
  501. package/schemas/implementation-plan.schema.json +19 -0
  502. package/schemas/proposed-learning.schema.json +19 -0
  503. package/schemas/research.schema.json +18 -0
  504. package/schemas/review.schema.json +29 -0
  505. package/schemas/run-manifest.schema.json +18 -0
  506. package/schemas/spec-challenge.schema.json +18 -0
  507. package/schemas/spec.schema.json +20 -0
  508. package/schemas/usage.schema.json +102 -0
  509. package/schemas/verification-proof.schema.json +29 -0
  510. package/schemas/wazir-manifest.schema.json +173 -0
  511. package/skills/README.md +40 -0
  512. package/skills/brainstorming/SKILL.md +77 -0
  513. package/skills/debugging/SKILL.md +50 -0
  514. package/skills/design/SKILL.md +61 -0
  515. package/skills/dispatching-parallel-agents/SKILL.md +128 -0
  516. package/skills/executing-plans/SKILL.md +70 -0
  517. package/skills/finishing-a-development-branch/SKILL.md +169 -0
  518. package/skills/humanize/SKILL.md +123 -0
  519. package/skills/init-pipeline/SKILL.md +124 -0
  520. package/skills/prepare-next/SKILL.md +20 -0
  521. package/skills/receiving-code-review/SKILL.md +123 -0
  522. package/skills/requesting-code-review/SKILL.md +105 -0
  523. package/skills/requesting-code-review/code-reviewer.md +108 -0
  524. package/skills/run-audit/SKILL.md +197 -0
  525. package/skills/scan-project/SKILL.md +41 -0
  526. package/skills/self-audit/SKILL.md +153 -0
  527. package/skills/subagent-driven-development/SKILL.md +154 -0
  528. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
  529. package/skills/subagent-driven-development/implementer-prompt.md +102 -0
  530. package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  531. package/skills/tdd/SKILL.md +23 -0
  532. package/skills/using-git-worktrees/SKILL.md +163 -0
  533. package/skills/using-skills/SKILL.md +95 -0
  534. package/skills/verification/SKILL.md +22 -0
  535. package/skills/wazir/SKILL.md +463 -0
  536. package/skills/writing-plans/SKILL.md +30 -0
  537. package/skills/writing-skills/SKILL.md +157 -0
  538. package/skills/writing-skills/anthropic-best-practices.md +122 -0
  539. package/skills/writing-skills/persuasion-principles.md +50 -0
  540. package/templates/README.md +20 -0
  541. package/templates/artifacts/README.md +10 -0
  542. package/templates/artifacts/accepted-learning.md +19 -0
  543. package/templates/artifacts/accepted-learning.template.json +12 -0
  544. package/templates/artifacts/author.md +74 -0
  545. package/templates/artifacts/author.template.json +19 -0
  546. package/templates/artifacts/clarification.md +21 -0
  547. package/templates/artifacts/clarification.template.json +12 -0
  548. package/templates/artifacts/execute-notes.md +19 -0
  549. package/templates/artifacts/implementation-plan.md +21 -0
  550. package/templates/artifacts/implementation-plan.template.json +11 -0
  551. package/templates/artifacts/learning-proposal.md +19 -0
  552. package/templates/artifacts/next-run-handoff.md +21 -0
  553. package/templates/artifacts/plan-review.md +19 -0
  554. package/templates/artifacts/proposed-learning.template.json +12 -0
  555. package/templates/artifacts/research.md +21 -0
  556. package/templates/artifacts/research.template.json +12 -0
  557. package/templates/artifacts/review-findings.md +19 -0
  558. package/templates/artifacts/review.template.json +11 -0
  559. package/templates/artifacts/run-manifest.template.json +8 -0
  560. package/templates/artifacts/spec-challenge.md +19 -0
  561. package/templates/artifacts/spec-challenge.template.json +11 -0
  562. package/templates/artifacts/spec.md +21 -0
  563. package/templates/artifacts/spec.template.json +12 -0
  564. package/templates/artifacts/verification-proof.md +19 -0
  565. package/templates/artifacts/verification-proof.template.json +11 -0
  566. package/templates/examples/accepted-learning.example.json +14 -0
  567. package/templates/examples/author.example.json +152 -0
  568. package/templates/examples/clarification.example.json +15 -0
  569. package/templates/examples/docs-claim.example.json +8 -0
  570. package/templates/examples/export-manifest.example.json +7 -0
  571. package/templates/examples/host-export-package.example.json +11 -0
  572. package/templates/examples/implementation-plan.example.json +17 -0
  573. package/templates/examples/proposed-learning.example.json +13 -0
  574. package/templates/examples/research.example.json +15 -0
  575. package/templates/examples/research.example.md +6 -0
  576. package/templates/examples/review.example.json +17 -0
  577. package/templates/examples/run-manifest.example.json +9 -0
  578. package/templates/examples/spec-challenge.example.json +14 -0
  579. package/templates/examples/spec.example.json +21 -0
  580. package/templates/examples/verification-proof.example.json +21 -0
  581. package/templates/examples/wazir-manifest.example.yaml +65 -0
  582. package/templates/task-definition-schema.md +99 -0
  583. package/tooling/README.md +20 -0
  584. package/tooling/src/adapters/context-mode.js +50 -0
  585. package/tooling/src/capture/command.js +376 -0
  586. package/tooling/src/capture/store.js +99 -0
  587. package/tooling/src/capture/usage.js +270 -0
  588. package/tooling/src/checks/branches.js +50 -0
  589. package/tooling/src/checks/brand-truth.js +110 -0
  590. package/tooling/src/checks/changelog.js +231 -0
  591. package/tooling/src/checks/command-registry.js +36 -0
  592. package/tooling/src/checks/commits.js +102 -0
  593. package/tooling/src/checks/docs-drift.js +103 -0
  594. package/tooling/src/checks/docs-truth.js +201 -0
  595. package/tooling/src/checks/runtime-surface.js +156 -0
  596. package/tooling/src/cli.js +116 -0
  597. package/tooling/src/command-options.js +56 -0
  598. package/tooling/src/commands/validate.js +320 -0
  599. package/tooling/src/doctor/command.js +91 -0
  600. package/tooling/src/export/command.js +77 -0
  601. package/tooling/src/export/compiler.js +498 -0
  602. package/tooling/src/guards/loop-cap-guard.js +52 -0
  603. package/tooling/src/guards/protected-path-write-guard.js +67 -0
  604. package/tooling/src/index/command.js +152 -0
  605. package/tooling/src/index/storage.js +1061 -0
  606. package/tooling/src/index/summarizers.js +261 -0
  607. package/tooling/src/loaders.js +18 -0
  608. package/tooling/src/project-root.js +22 -0
  609. package/tooling/src/recall/command.js +225 -0
  610. package/tooling/src/schema-validator.js +30 -0
  611. package/tooling/src/state-root.js +40 -0
  612. package/tooling/src/status/command.js +71 -0
  613. package/wazir.manifest.yaml +135 -0
  614. package/workflows/README.md +19 -0
  615. package/workflows/author.md +42 -0
  616. package/workflows/clarify.md +38 -0
  617. package/workflows/design-review.md +46 -0
  618. package/workflows/design.md +44 -0
  619. package/workflows/discover.md +37 -0
  620. package/workflows/execute.md +48 -0
  621. package/workflows/learn.md +38 -0
  622. package/workflows/plan-review.md +42 -0
  623. package/workflows/plan.md +39 -0
  624. package/workflows/prepare-next.md +37 -0
  625. package/workflows/review.md +40 -0
  626. package/workflows/run-audit.md +41 -0
  627. package/workflows/spec-challenge.md +41 -0
  628. package/workflows/specify.md +38 -0
  629. package/workflows/verify.md +37 -0
@@ -0,0 +1,782 @@
1
+ # Push and Sync — Architecture Expertise Module
2
+
3
+ > Push and Sync covers two related mobile concerns: push notifications (server-initiated messages to devices) and data synchronization (keeping local and remote data consistent). Both are fundamental to mobile UX — push drives re-engagement and real-time awareness, sync enables offline capability and fast local reads. They are complementary but distinct: push is a one-way signaling mechanism from server to device, sync is a bidirectional data consistency protocol. They often work together (a silent push triggers a sync), but conflating them leads to poor architecture.
4
+
5
+ > **Category:** Mobile Architecture
6
+ > **Complexity:** Moderate
7
+ > **Applies when:** Mobile applications that need to notify users of events or keep local data synchronized with a remote backend
8
+
9
+ ---
10
+
11
+ ## What This Is (and What It Isn't)
12
+
13
+ ### Push Notifications
14
+
15
+ Push notifications are server-initiated messages delivered to a user's device through platform-specific relay services — Apple Push Notification service (APNs) for iOS and Firebase Cloud Messaging (FCM) for Android. The device does not poll for these messages. Instead, each device maintains a persistent encrypted connection to the platform's relay service, and the server sends messages through this relay.
16
+
17
+ There are three categories of push notification:
18
+
19
+ **Alert/Display notifications.** These produce a visible banner, badge, or sound. The user sees them. They are the "push notification" that product managers discuss — the thing that appears on the lock screen. On iOS, these require explicit user opt-in (with opt-in rates averaging 56% as of 2025). On Android, they are enabled by default but users can revoke per-channel (opt-in rates have dropped from 85% to 67% in a single year).
20
+
21
+ **Silent/Data notifications.** These wake the app in the background without showing anything to the user. iOS calls them "content-available" pushes. Android calls them "data messages." They exist to trigger background processing — typically a data sync. iOS throttles them aggressively: a few per hour at most, and the system may delay or drop them based on battery level and app usage patterns. The app gets roughly 30 seconds of background execution time. If the user has force-killed the app, silent pushes are not delivered on iOS at all until the user reopens the app.
22
+
23
+ **Topic/Channel notifications.** Both APNs and FCM support subscribing devices to named topics. A server publishes to a topic, and all subscribed devices receive the message. This is efficient for broadcast scenarios (news alerts, sports scores) where the same message goes to many devices. FCM also supports condition-based targeting (e.g., send to devices subscribed to topic A AND topic B).
24
+
25
+ ### Data Synchronization
26
+
27
+ Data sync is the process of keeping local (on-device) data consistent with remote (server-side) data. Unlike push, sync is fundamentally about data, not signals. The local database is treated as the primary source of truth for UI rendering, and the sync process reconciles it with the server.
28
+
29
+ There are three sync directions:
30
+
31
+ **Pull-based (client-initiated).** The client polls the server at intervals or on user action. Simple to implement. Wastes bandwidth when nothing has changed. Introduces latency equal to the polling interval. Appropriate for low-frequency data (settings, profile information).
32
+
33
+ **Push-based (server-initiated).** The server notifies the client when data changes, either via a persistent connection (WebSocket, SSE) or via a silent push notification that triggers a fetch. Minimizes latency and bandwidth waste. Requires infrastructure for connection management or push delivery. WebSockets provide full-duplex communication but require reconnection logic on mobile (the OS will kill background connections). SSE offers automatic reconnection but lacks native mobile SDK support and is unidirectional.
34
+
35
+ **Bidirectional (conflict-prone).** Both client and server can modify data, and changes propagate in both directions. This is the architecture of collaborative apps, offline-first apps, and any system where the user creates or modifies data while offline. It requires a conflict resolution strategy because two parties can modify the same record independently.
36
+
37
+ ### What They Are Not
38
+
39
+ **Push is not sync.** A push notification tells the device "something happened." It does not deliver the data itself (payloads are limited to 4 KB on APNs, 4 KB on FCM). A common anti-pattern is trying to encode meaningful data in push payloads instead of using push as a trigger for a proper sync fetch.
40
+
41
+ **Sync is not real-time messaging.** Sync ensures eventual consistency between local and remote data stores. Real-time messaging (chat, live cursors, collaborative editing) requires sub-second delivery with ordering guarantees. Sync tolerates seconds or minutes of delay. Conflating the two leads to overengineering sync infrastructure or underengineering messaging infrastructure.
42
+
43
+ **Push is not reliable delivery.** APNs and FCM provide best-effort delivery, not guaranteed delivery. APNs stores only the most recent notification per device if the device is offline. FCM stores up to 100 pending messages per device for up to 28 days. Neither guarantees order of delivery. Applications that require guaranteed delivery must implement their own acknowledgment and retry logic on top of push.
44
+
45
+ ---
46
+
47
+ ## When to Use It
48
+
49
+ ### Push Notifications — The Qualifying Conditions
50
+
51
+ **Real-time user awareness is a product requirement.** Chat applications (new message), e-commerce (order status updates), ride-sharing (driver arriving), social media (new follower, comment). The user needs to know something happened without opening the app. WhatsApp delivers message notifications instantly by combining WebSocket connections in the foreground with push notifications when the app is backgrounded or closed.
52
+
53
+ **Re-engagement is a measured business metric.** The product team tracks DAU/MAU ratios and push notifications are a lever. News apps, social platforms, and marketplace apps use push to bring users back. Airbnb sends push notifications when a host responds to an inquiry, and the notification links directly to the conversation — reducing time-to-booking.
54
+
55
+ **Time-sensitive actions require user response.** Two-factor authentication codes, appointment reminders, delivery windows, payment confirmations. The value of the notification degrades rapidly with delay.
56
+
57
+ **Background data refresh improves perceived performance.** Silent push triggers a background sync so that when the user opens the app, fresh data is already loaded. Email clients use this pattern — a silent push arrives, the client fetches new mail in the background, and the inbox appears current when opened. This creates the perception of instant loading.
58
+
59
+ ### Data Sync — The Qualifying Conditions
60
+
61
+ **Offline capability is a hard requirement.** Field service apps (technicians in areas without connectivity), note-taking apps (Notion, Bear, Apple Notes), healthcare apps (clinicians in hospital dead zones). The user must be able to read and write data without network access, and changes must reconcile when connectivity returns.
62
+
63
+ **Local-first rendering for performance.** Even apps that are always online benefit from reading from a local database and syncing in the background. This eliminates loading spinners on app launch and makes the UI feel instant. Linear uses this pattern — the entire workspace is synced locally, and the UI reads from a local store. Queries are instant regardless of network latency.
64
+
65
+ **Multi-device consistency.** A user's data must be consistent across their phone, tablet, and web browser. iCloud sync, Google Drive sync, and cross-device bookmark sync are canonical examples. The sync engine must handle the same user modifying data on two devices simultaneously.
66
+
67
+ **Collaborative data modification.** Multiple users editing the same data — shared documents (Google Docs, Figma), shared task boards (Trello, Asana), shared shopping lists. This is the hardest sync problem because conflicts between different users are common and must be resolved without data loss.
68
+
69
+ ---
70
+
71
+ ## When NOT to Use It
72
+
73
+ This section is as important as the previous one. Both push notifications and data sync carry significant complexity, platform constraints, and user-facing consequences when misapplied.
74
+
75
+ ### Push Notifications — The Disqualifying Conditions
76
+
77
+ **Over-notification drives uninstalls.** This is not hypothetical — it is measured and substantial. Sending 3-6 push notifications per week causes 40% of users to disable notifications entirely. Sending just one push notification per week leads to 6% of users uninstalling the app outright. 46% of users opt out after receiving 2-5 messages in a single week. The marginal re-engagement value of one more notification must be weighed against permanent user loss. Many product teams treat push as free — it is not. Every notification is a withdrawal from a finite trust account.
78
+
79
+ **The notification has no clear user value.** "We haven't seen you in a while!" notifications are the canonical anti-pattern. They serve the business, not the user. Users recognize this and it erodes trust. Notifications should communicate something the user cares about and cannot easily discover on their own. If the user would not be disappointed to miss the information, it should not be a push notification.
80
+
81
+ **The content is not time-sensitive.** Marketing promotions, weekly digests, feature announcements — these belong in in-app messages, email, or app badges, not push. Push notifications interrupt the user's current activity. The interruption is justified only when the information is time-bounded (your ride is arriving, your food is ready, your flight is delayed).
82
+
83
+ **You cannot segment or personalize.** Broadcasting the same notification to all users is almost always wrong. A sports app that sends every score update to all users will annoy anyone who does not follow that sport. Segmentation by user preferences, behavior, and context is a prerequisite for push, not an optimization.
84
+
85
+ **Platform restrictions make delivery unreliable for your use case.** On iOS, if the user has denied notification permission, you cannot send any push (including silent push on some configurations). On Android, starting with Android 13, notification permission requires explicit opt-in. If your target audience has low opt-in rates (fitness apps average 45% opt-in on iOS), push cannot be your primary communication channel.
86
+
87
+ **You lack analytics infrastructure to measure impact.** Without delivery confirmation, open rate tracking, and conversion attribution, you cannot distinguish valuable notifications from noise. Sending push without measurement is spending a finite resource (user attention) without knowing the return.
88
+
89
+ ### Data Sync — The Disqualifying Conditions
90
+
91
+ **The app is read-only or write-rarely.** A news reader, weather app, or stock ticker consumes server data but rarely or never writes back. Full bidirectional sync is unnecessary overhead. Simple API fetching with local caching (HTTP cache headers, ETag-based conditional requests) achieves the same UX with a fraction of the complexity.
92
+
93
+ **Data volume makes local replication impractical.** If the server holds 50 GB of data per user and the user typically accesses 1% of it on mobile, syncing everything locally is wasteful. Instead, cache recently accessed data and fetch on demand. A media streaming app does not sync its entire catalog locally.
94
+
95
+ **Background sync drains battery disproportionately to value.** Apps that sync frequently in the background — particularly those using GPS, network polling, or continuous WebSocket connections — consume significant battery. Users notice. Facebook, Instagram, and Snapchat are consistently cited as top battery-draining apps precisely because of aggressive background sync and data fetching. If your sync frequency exceeds what the data freshness actually requires, you are trading battery life for data that nobody will look at before the next foreground sync.
96
+
97
+ **Conflict resolution complexity exceeds team capacity.** Bidirectional sync with conflict resolution is genuinely hard. If the team does not have experience with CRDTs, operational transforms, or at minimum vector clocks, implementing a custom sync engine is a high-risk endeavor. Using a managed solution (Firebase Realtime Database, Realm Sync, AWS AppSync) is preferable to a half-implemented custom sync that silently loses data.
98
+
99
+ **Regulatory constraints on local data storage.** Healthcare (HIPAA), financial (PCI-DSS), and government applications may prohibit storing certain data on the device or require encryption at rest with specific key management. Sync engines that cache data locally must comply with these constraints, adding implementation cost that may not be justified.
100
+
101
+ ---
102
+
103
+ ## How It Works
104
+
105
+ ### Push Notification Architecture
106
+
107
+ #### Platform Relay Services
108
+
109
+ Both iOS and Android use a relay service model. The app server never connects directly to the device. Instead:
110
+
111
+ 1. **Device registration.** On app launch, the app requests a device token from the OS. On iOS, the app calls `UIApplication.registerForRemoteNotifications()`, which returns a device token from APNs. On Android, the app calls `FirebaseMessaging.getInstance().getToken()`, which returns a registration token from FCM. These tokens are opaque, platform-specific identifiers.
112
+
113
+ 2. **Token storage.** The app sends the device token to the app server, which stores it in a device registry associated with the user account. A single user may have multiple tokens (phone + tablet). Tokens can change at any time — the app must re-register on every launch and send updated tokens to the server.
114
+
115
+ 3. **Message submission.** The app server sends a message to the platform relay service (APNs or FCM), specifying the target device token(s) and the payload. The relay service delivers the message to the device over its persistent connection.
116
+
117
+ 4. **Device delivery.** The OS receives the message, wakes the app (for data messages) or displays the notification (for alert messages), and the app handles the payload.
118
+
119
+ #### APNs Architecture (iOS)
120
+
121
+ APNs uses HTTP/2 with TLS 1.2+ for server-to-APNs communication. The app server authenticates using either a TLS certificate (per-app) or a JWT token (per-team, recommended). Each request is a POST to `api.push.apple.com` (production) or `api.sandbox.push.apple.com` (development).
122
+
123
+ Key constraints:
124
+ - Maximum payload size: 4 KB (4096 bytes)
125
+ - APNs stores only the most recent notification per device per app if the device is offline
126
+ - Token-based authentication JWTs must be refreshed every 20-60 minutes; APNs rejects tokens older than one hour
127
+ - Device tokens are environment-specific — a sandbox token will not work in production
128
+ - APNs returns a 410 status code for invalidated tokens; the server must remove these from its registry
129
+
130
+ Notification channels on iOS are managed through `UNNotificationCategory` and `UNNotificationAction`, allowing the app to define interactive notification types with custom buttons.
131
+
132
+ #### FCM Architecture (Android)
133
+
134
+ FCM acts as a unified relay. On Android, the device maintains a single persistent TCP/IP connection to FCM servers, established at device boot. This connection is shared across all apps on the device — only one socket is needed regardless of how many FCM-enabled apps are installed.
135
+
136
+ FCM also brokers iOS notifications. By uploading APNs credentials to Firebase, developers can use FCM's API to target both Android and iOS with a single API call. FCM translates the message and forwards it to APNs for iOS delivery.
137
+
138
+ Key constraints:
139
+ - Maximum payload: 4 KB for notification messages, 4 KB for data messages
140
+ - FCM stores up to 100 pending messages per device for up to 28 days
141
+ - High-priority messages bypass Android's Doze mode and deliver immediately, waking the device if necessary
142
+ - Normal-priority messages are batched and delivered during Doze maintenance windows
143
+ - Starting Android 13, apps must request `POST_NOTIFICATIONS` runtime permission
144
+
145
+ Notification channels on Android (API 26+) allow users to control notification behavior per channel — sound, vibration, importance level, and whether the channel is enabled at all. The app defines channels; the user controls them.
146
+
147
+ #### Silent Push as Sync Trigger
148
+
149
+ The most architecturally significant push pattern is using silent push to trigger background data sync:
150
+
151
+ ```
152
+ Server detects data change
153
+ → Server sends silent push (content-available: 1 on iOS, data-only message on FCM)
154
+ → OS wakes app in background
155
+ → App fetches changed data from server API
156
+ → App updates local database
157
+ → UI reflects changes when user opens app
158
+ ```
159
+
160
+ This pattern combines the efficiency of push (no polling) with the reliability of a proper API fetch (full data, not limited to 4 KB). However, it inherits all the unreliability of silent push — iOS throttles delivery, force-killed apps do not receive them, and there is no delivery guarantee.
161
+
162
+ A robust implementation combines silent push with periodic background fetch as a fallback:
163
+
164
+ ```
165
+ Primary: Silent push → immediate background sync
166
+ Fallback: BGTaskScheduler (iOS) / WorkManager (Android) → periodic sync
167
+ Last resort: Foreground fetch on app open
168
+ ```
169
+
170
+ ### Data Sync Architecture
171
+
172
+ #### Pull-Based Sync (Polling)
173
+
174
+ The simplest sync model. The client requests data from the server at regular intervals or on specific triggers (app open, pull-to-refresh, timer).
175
+
176
+ **Delta sync** is essential for pull-based models at scale. Instead of fetching all data on every poll, the client sends a `lastSyncTimestamp` or `syncToken`, and the server returns only records that changed since that point. This reduces bandwidth from O(total data) to O(changed data) per sync cycle.
177
+
178
+ ```
179
+ Client: GET /api/items?since=2025-03-07T10:00:00Z
180
+ Server: returns [{id: 42, title: "updated", updated_at: "2025-03-07T14:30:00Z"}, ...]
181
+ Client: stores items, updates lastSyncTimestamp to max(updated_at)
182
+ ```
183
+
184
+ **Cursor-based pagination** handles large delta sets. The server returns a page of changes plus a cursor for the next page. The client pages through all changes before updating its sync checkpoint.
185
+
186
+ #### Push-Based Sync (Persistent Connections)
187
+
188
+ For apps that need sub-second data freshness while in the foreground, a persistent connection delivers changes as they occur.
189
+
190
+ **WebSockets** provide full-duplex communication. The client opens a WebSocket connection on app foreground and receives real-time updates. The client can also send changes through the same connection. WhatsApp, Slack, and Discord use WebSocket connections for real-time message delivery while the app is in the foreground.
191
+
192
+ Mobile-specific WebSocket concerns:
193
+ - The OS kills background WebSocket connections to conserve battery — WebSockets are foreground-only on mobile
194
+ - Network transitions (Wi-Fi to cellular) break the connection — reconnection with exponential backoff is mandatory
195
+ - The client must handle message ordering across reconnections — missed messages during disconnection must be fetched via a catch-up API call
196
+ - Connection keepalive pings prevent intermediate proxies from closing idle connections (typical interval: 30 seconds)
197
+
198
+ **Server-Sent Events (SSE)** are simpler than WebSockets (unidirectional, server-to-client only) and offer built-in automatic reconnection via the `Last-Event-ID` header. However, native SSE support on mobile platforms is limited — both iOS and Android require custom HTTP streaming implementations or third-party libraries.
199
+
200
+ #### Conflict Resolution Strategies
201
+
202
+ When two parties modify the same data independently (user edits on two devices while offline, or user edits while another user edits the same record), conflicts arise during sync. There are five primary resolution strategies:
203
+
204
+ **Last Write Wins (LWW).** The most recent write (by timestamp) overwrites the earlier one. Simple to implement but silently discards data. Appropriate for user preferences, settings, and single-user data where conflicts are rare and the most recent value is almost always correct. Figma uses a variant of LWW at the property level — if two users change the same property on the same object, the last value sent to the server wins.
205
+
206
+ **Server Wins / Client Wins.** A fixed precedence rule. Server-wins is appropriate when the server is authoritative (e.g., pricing data, inventory counts). Client-wins is rare but occasionally used in personal-device scenarios where the local state is always considered correct.
207
+
208
+ **Field-Level Merge.** Instead of treating the entire record as the unit of conflict, merge at the field level. If user A changes the `title` and user B changes the `description` of the same record, both changes are preserved because they affected different fields. This works well for structured records with independent fields. Linear uses this approach for issue metadata — status, assignee, and labels can be changed independently without conflict.
209
+
210
+ **CRDTs (Conflict-free Replicated Data Types).** Mathematical data structures that guarantee convergence without coordination. Two replicas can be modified independently and merged deterministically — the result is the same regardless of merge order. CRDTs come in two varieties:
211
+ - **State-based (CvRDTs):** Replicas exchange their full state and merge using a defined join operation. Simple but bandwidth-heavy.
212
+ - **Operation-based (CmRDTs):** Replicas exchange operations (insert, delete) and apply them commutatively. More bandwidth-efficient but requires reliable delivery of all operations.
213
+
214
+ Figma uses a CRDT-inspired approach for its collaborative design tool. Each document is a tree of objects, and conflict resolution operates at the property level. However, Figma discovered that CRDTs at scale produce tombstone bloat — documents accumulated 10+ million tombstones from deleted shapes, each 32 bytes, inflating files to gigabytes. They implemented aggressive compaction: when a document exceeds 1 million tombstones, the server creates a new snapshot and discards history older than 7 days.
215
+
216
+ **Operational Transform (OT).** Transforms concurrent operations so they can be applied in any order and produce the same result. Google Docs uses OT for text editing. Each character insertion or deletion is an operation with a position. When two users type at the same position simultaneously, OT transforms the positions so both insertions are preserved. OT requires a central server to determine operation ordering, making it less suitable for offline-first mobile apps.
217
+
218
+ **Manual Resolution.** Present the conflict to the user and let them choose. Git uses this for merge conflicts. Some mobile apps use it for critical data (e.g., medical records) where automated resolution could be dangerous. This should be a last resort — users find conflict resolution dialogs confusing and annoying.
219
+
220
+ #### Background Sync APIs
221
+
222
+ **iOS — BGTaskScheduler.** Starting iOS 13, `BGTaskScheduler` is the primary API for background work. It offers two task types:
223
+ - `BGAppRefreshTask`: Short tasks (up to 30 seconds) for fetching small amounts of data. iOS determines when to execute based on user usage patterns, battery level, and network availability.
224
+ - `BGProcessingTask`: Longer tasks (minutes) for significant work like database maintenance or large sync operations. Can require power connection and network availability.
225
+
226
+ The OS controls execution timing — you register a task and the OS runs it when conditions are favorable. There is no guaranteed schedule. Apps that the user opens frequently get more background time. Apps the user ignores get less.
227
+
228
+ **Android — WorkManager.** WorkManager is the recommended API for deferrable, guaranteed background work on Android. It survives app exits and device reboots. Key capabilities:
229
+ - Constraints: require network, require charging, require device idle
230
+ - Backoff policies: linear or exponential
231
+ - Chaining: sequential or parallel work chains
232
+ - Unique work: ensure only one instance of a named task runs
233
+ - WorkManager respects Doze mode and App Standby — it schedules work during maintenance windows
234
+
235
+ **Cross-platform — Silent push + periodic fallback.** The most robust background sync strategy combines silent push for immediate updates with periodic background tasks as a fallback. The silent push provides low-latency sync for critical changes, while the periodic task catches anything the push missed (due to throttling, delivery failure, or the app being force-killed).
236
+
237
+ ### Sync Status Tracking
238
+
239
+ Every locally stored record needs sync metadata:
240
+
241
+ ```
242
+ Record {
243
+ id: string // Server-assigned ID (null if created offline)
244
+ localId: string // Client-assigned ID (UUID, always present)
245
+ data: {...} // The actual record data
246
+ syncStatus: enum // 'synced' | 'pending_create' | 'pending_update' | 'pending_delete' | 'conflicted'
247
+ localModifiedAt: Date // When the client last modified this record
248
+ serverModifiedAt: Date // Last known server modification timestamp
249
+ version: number // Optimistic concurrency version (optional)
250
+ conflictData: {...} // Server version of data when conflict detected (optional)
251
+ }
252
+ ```
253
+
254
+ The UI reads from the local store regardless of sync status. Pending changes are displayed immediately (optimistic UI). A sync indicator shows the user when changes are still uploading. Conflicted records are flagged for resolution.
255
+
256
+ ---
257
+
258
+ ## Trade-Offs Matrix
259
+
260
+ | Dimension | Push Notifications | Data Sync (Pull) | Data Sync (Push/WebSocket) | Data Sync (Bidirectional/Offline) |
261
+ |---|---|---|---|---|
262
+ | **Latency** | Seconds (best-effort) | Polling interval (seconds to minutes) | Sub-second (while connected) | Eventually consistent (seconds to hours) |
263
+ | **Battery impact** | Minimal (uses OS relay) | Proportional to poll frequency | High while connected (foreground only) | Moderate (background sync bursts) |
264
+ | **Bandwidth** | Minimal (< 4 KB per message) | Proportional to poll frequency and data size | Efficient (delta only) | Efficient with delta sync, expensive with full sync |
265
+ | **Offline support** | Platform queues 1 (APNs) to 100 (FCM) messages | No (requires connectivity) | No (connection required) | Yes (full offline read/write) |
266
+ | **Implementation complexity** | Low (platform SDKs handle delivery) | Low (HTTP polling) | Moderate (connection management, reconnection) | High (conflict resolution, sync engine) |
267
+ | **Reliability** | Best-effort, no guarantee | Reliable (client controls retry) | Connection-dependent | High with proper retry/queue |
268
+ | **Server infrastructure** | Platform relay (APNs/FCM) + token registry | Standard REST API | WebSocket server with connection state | Sync engine, conflict resolution, change tracking |
269
+ | **User permission required** | Yes (iOS alert notifications) | No | No | No |
270
+ | **Scalability concern** | Token registry size, topic fanout | Server load from polling | Concurrent WebSocket connections | Sync computation per client, conflict resolution load |
271
+ | **Data freshness guarantee** | None (delivery not guaranteed) | Bounded by poll interval | Real-time while connected | Eventual consistency |
272
+
273
+ ---
274
+
275
+ ## Evolution Path
276
+
277
+ ### Stage 1: Simple Fetch + Basic Push
278
+
279
+ The app fetches data on launch via REST API. Push notifications are alert-only (user-visible) for critical events. No local database — data lives in memory and is re-fetched on every app open.
280
+
281
+ **When this breaks:** App launch feels slow on poor networks. Users complain about stale data. Product wants "instant" updates.
282
+
283
+ ### Stage 2: Local Cache + Silent Push
284
+
285
+ Introduce a local database (SQLite/Room on Android, Core Data/SQLite on iOS, Hive/Drift on Flutter). Fetch data on launch and cache it. Use silent push to trigger background refresh so data is fresh when the user opens the app.
286
+
287
+ **When this breaks:** Users start creating/editing data on mobile. You need to handle local writes, upload queue, and retry logic. Two devices editing the same data creates conflicts.
288
+
289
+ ### Stage 3: Delta Sync + Upload Queue
290
+
291
+ Implement delta sync — the client sends `lastSyncTimestamp` and receives only changed records. Local writes go into an upload queue (WorkManager on Android, BGTaskScheduler on iOS) that retries with exponential backoff. Conflict detection via server version numbers (optimistic concurrency).
292
+
293
+ **When this breaks:** Real-time collaboration is needed. Poll-based sync introduces unacceptable latency. Users expect to see each other's changes in seconds.
294
+
295
+ ### Stage 4: Real-Time Sync + Conflict Resolution
296
+
297
+ Add WebSocket connections for foreground real-time updates. Implement field-level conflict resolution or CRDTs for collaborative data. Silent push + periodic background sync handles background updates. The local database is the single source of truth — all UI reads from local, sync handles consistency.
298
+
299
+ **When this breaks:** Scale. Thousands of concurrent WebSocket connections per server. CRDT tombstone bloat. Sync computation becomes a server bottleneck. You need a dedicated sync infrastructure team.
300
+
301
+ ### Stage 5: Managed Sync Infrastructure
302
+
303
+ Adopt a managed sync platform (Firebase Realtime Database, Realm Sync, AWS AppSync, PowerSync, ElectricSQL) or build a dedicated sync service with its own team. The sync engine becomes infrastructure, not application code.
304
+
305
+ ---
306
+
307
+ ## Failure Modes
308
+
309
+ ### Push Notification Failures
310
+
311
+ **Token management failures.** Device tokens change without warning. APNs invalidates tokens when the user reinstalls the app, restores from backup, or upgrades the OS. FCM tokens can be rotated by the SDK at any time. If the server sends to a stale token, APNs returns a 410 status; FCM returns a `NotRegistered` error. The server must handle these responses and remove the invalid token from its registry. Failure to do so means the token registry grows with dead tokens, wasting API calls and skewing delivery metrics. A common incident: a server accumulates millions of stale tokens over months, sending push requests that all fail, consuming API quota and server resources.
312
+
313
+ **Notification fatigue and user attrition.** The data is clear: 40% of users disable notifications after receiving 3-6 per week. 6% uninstall the app after just one notification per week. 95% of users who opt in but receive no notification in 90 days churn. The sweet spot is narrow — too few and you lose engagement, too many and you lose the user permanently. Apps that treat push as a free engagement channel without measuring opt-out rates and uninstall correlation are on a predictable path to declining DAU.
314
+
315
+ **Delivery unreliability.** APNs stores only the last notification per app if the device is offline. If you send three notifications while the user's phone is in airplane mode, they receive only the last one. FCM is more generous (up to 100 messages, 28 days) but still not guaranteed. High-priority FCM messages bypass Doze mode, but Android deprioritizes apps that abuse high-priority messaging. Silent push on iOS is throttled to a few per hour and is not delivered to force-killed apps. Any architecture that depends on guaranteed push delivery will fail intermittently and silently.
316
+
317
+ **Platform-specific behavioral differences.** The same notification behaves differently on iOS and Android. iOS groups notifications by thread identifier; Android groups by channel. iOS collapses notifications with the same `apns-collapse-id`; FCM uses `collapse_key`. Foreground handling differs — on iOS the app must explicitly handle foreground notifications via `UNUserNotificationCenterDelegate`; on Android, FCM notification messages are handled by the system tray automatically in the background but delivered to the app's `onMessageReceived` in the foreground. These differences create bugs that only appear on one platform.
318
+
319
+ ### Data Sync Failures
320
+
321
+ **Conflict data loss.** The most dangerous sync failure is silent data loss during conflict resolution. A Last-Write-Wins policy silently discards the earlier write. If the discarded write was a 30-minute form entry that the user completed on a plane, that data is gone. The user discovers the loss hours or days later and has no recourse. Mitigation: for user-generated content, never use LWW without preserving the overwritten version in a conflict log that the user can access.
322
+
323
+ **Sync loop / infinite sync.** A bug in sync logic causes the client to mark a record as modified during the sync process itself (e.g., a computed field updates when the record is written to the local DB). This triggers another sync cycle, which writes again, triggering another sync. The app burns battery and bandwidth in an infinite loop. Mitigation: distinguish between user modifications (trigger sync) and sync-applied modifications (do not trigger sync) using a flag or separate write path.
324
+
325
+ **Partial sync corruption.** A sync operation fetches 500 records but the network drops at record 300. If the client committed the first 300 and updated its sync checkpoint, it will never re-fetch those 300 — but it also missed 200. If it did not commit, it must re-fetch all 500. The solution is transactional sync: fetch all changes, apply them in a single database transaction, and update the sync checkpoint atomically. If any step fails, the entire batch is rolled back and retried.
326
+
327
+ **Background sync battery drain.** Aggressive background sync is the primary reason users uninstall "battery drain" apps. Each background sync wakes the radio (200-600 ms ramp-up on cellular), transfers data, and processes it. On cellular networks, the radio stays in a high-power state for 10-20 seconds after the last transmission (tail energy). An app that syncs every 5 minutes creates 288 radio wake cycles per day, each with tail energy. Mitigation: batch sync operations, use platform-provided constraints (require Wi-Fi, require charging), and respect OS throttling.
328
+
329
+ **Clock skew in timestamp-based sync.** Delta sync relies on timestamps. If the client clock is wrong (common — users change time zones, device clocks drift), the `lastSyncTimestamp` may be in the future (missing new data) or in the past (re-fetching old data). Server-generated timestamps for sync checkpoints are safer than client timestamps. Using monotonically increasing sequence numbers instead of timestamps eliminates clock skew entirely.
330
+
331
+ **Tombstone accumulation.** Deleted records cannot simply be removed from the server because clients that have not yet synced need to know the record was deleted. Instead, deleted records are marked with a `deleted_at` timestamp (tombstoned). Over time, tombstones accumulate. Figma encountered documents with 10+ million tombstones consuming gigabytes. Mitigation: implement tombstone compaction — after all known clients have synced past the deletion timestamp, the tombstone can be permanently removed. This requires tracking per-client sync checkpoints.
332
+
333
+ ---
334
+
335
+ ## Technology Landscape
336
+
337
+ ### Push Notification Services
338
+
339
+ **Apple Push Notification service (APNs).** Apple's proprietary relay. Required for all iOS push. HTTP/2 API with JWT or certificate authentication. Free to use (included with Apple Developer Program). No third-party alternative exists — all iOS push goes through APNs, even when using FCM or OneSignal (they proxy through APNs).
340
+
341
+ **Firebase Cloud Messaging (FCM).** Google's cross-platform push service. Handles Android natively and proxies to APNs for iOS. Free tier with no message limits. Supports topics, device groups, and conditional targeting. Provides delivery analytics via the FCM Aggregate Delivery Data API. The dominant choice for Android push and a common choice for unified cross-platform push.
342
+
343
+ **OneSignal.** A push notification platform built on top of APNs and FCM. Adds segmentation, A/B testing, automation, and analytics that FCM lacks out of the box. Free tier supports up to 10,000 subscribers. Maintains 99.95% uptime. Preferred by product and marketing teams who need engagement tools beyond raw push delivery. More feature-rich for notification management but adds a dependency and potential single point of failure.
344
+
345
+ **Amazon SNS (Simple Notification Service).** AWS's pub/sub messaging service that supports mobile push to APNs, FCM, and ADM (Amazon Device Messaging). Integrates with the AWS ecosystem. Pricing is per-million messages. Suitable for teams already on AWS who want push integrated with their existing infrastructure.
346
+
347
+ **Pusher Beams.** Push notification service from Pusher. Simpler API surface than OneSignal. Supports APNs and FCM. Limited free tier. Less feature-rich than OneSignal but simpler to integrate for developers who just need reliable delivery.
348
+
349
+ ### Real-Time Sync and Messaging
350
+
351
+ **Firebase Realtime Database / Cloud Firestore.** Google's managed real-time database with built-in sync. Data changes propagate to all connected clients in milliseconds. Offline support with local persistence. Conflict resolution is LWW by default. Firestore adds document-based structure, queries, and better scaling. The fastest path from zero to synced mobile app. Limitations: vendor lock-in, limited query expressiveness, cost unpredictability at scale.
352
+
353
+ **Realm Sync (MongoDB Atlas Device Sync).** Object database with automatic bidirectional sync. Conflict resolution uses operational transform with field-level granularity. Strong offline support. Integrates with MongoDB Atlas on the backend. More expressive data model than Firestore. Limitations: tied to MongoDB ecosystem, Realm SDK must be used as the local database.
354
+
355
+ **AWS AppSync.** Managed GraphQL API with real-time subscriptions and offline support. Uses DynamoDB, Aurora, or Lambda as data sources. Conflict resolution configurable: auto-merge, optimistic concurrency, or custom Lambda resolvers. Good fit for teams on AWS who want GraphQL. Limitations: GraphQL complexity, AWS vendor lock-in.
356
+
357
+ **PowerSync.** Open-source sync engine for Postgres-backed apps. Syncs a subset of Postgres data to SQLite on the device. Supports partial replication (sync rules define which data each user gets). Handles conflict resolution via server-side rules. Good fit for existing Postgres backends that want to add offline-capable mobile clients without replacing the database.
358
+
359
+ **ElectricSQL.** Open-source active-active replication from Postgres to SQLite. Uses CRDTs for conflict-free sync. Designed for local-first applications. Early-stage but promising for teams who want true local-first with Postgres as the backend.
360
+
361
+ **Ably.** Managed real-time messaging platform. WebSocket-based with automatic fallback to long-polling. Guarantees message ordering and exactly-once delivery (unlike raw WebSockets). Provides presence detection (who is online). Suitable for chat, live updates, and collaborative features. Pricing is per-message and per-connection.
362
+
363
+ **Pusher Channels.** Real-time messaging via WebSockets. Simpler than Ably with fewer guarantees (at-least-once delivery, not exactly-once). Presence channels for tracking online users. Private channels for authenticated access. Suitable for live dashboards, notifications, and simple real-time features. More affordable than Ably at moderate scale.
364
+
365
+ ### Background Sync APIs (Platform-Native)
366
+
367
+ | Platform | API | Purpose | Constraints |
368
+ |---|---|---|---|
369
+ | iOS 13+ | `BGTaskScheduler` | Register background refresh and processing tasks | OS controls timing; no guaranteed schedule |
370
+ | iOS | `URLSession` background transfers | Large file uploads/downloads that survive app termination | System-managed, completes even if app is killed |
371
+ | Android | `WorkManager` | Deferrable, guaranteed background work | Survives reboot; respects Doze; supports constraints |
372
+ | Android | `JobScheduler` (API 21+) | Predecessor to WorkManager, lower-level | WorkManager is preferred; JobScheduler is legacy |
373
+ | Flutter | `workmanager` plugin | Cross-platform background task scheduling | Wraps WorkManager (Android) and BGTaskScheduler (iOS) |
374
+ | React Native | `react-native-background-fetch` | Cross-platform background fetch | Wraps platform APIs with unified interface |
375
+
376
+ ---
377
+
378
+ ## Decision Tree
379
+
380
+ ```
381
+ START: Does your app need to communicate with users when the app is closed?
382
+
383
+ ├─ YES → Push Notifications
384
+ │ │
385
+ │ ├─ Are messages time-sensitive and user-specific?
386
+ │ │ ├─ YES → Targeted alert push (APNs + FCM)
387
+ │ │ └─ NO → Consider in-app messaging or email instead
388
+ │ │
389
+ │ ├─ Do you need to broadcast to many users simultaneously?
390
+ │ │ ├─ YES → Topic-based push (FCM topics, APNs topic)
391
+ │ │ └─ NO → Targeted push with device tokens
392
+ │ │
393
+ │ └─ Do you need to trigger background data refresh?
394
+ │ ├─ YES → Silent push + background fetch fallback
395
+ │ └─ NO → Alert push only
396
+
397
+ ├─ NO → Skip push notifications entirely
398
+
399
+ └─ Does your app need to keep local data in sync with a server?
400
+
401
+ ├─ NO → Simple API fetch on demand, no sync needed
402
+
403
+ └─ YES → Data Sync
404
+
405
+ ├─ Is the app read-only (no user writes)?
406
+ │ ├─ YES → Pull-based sync (polling or silent push trigger)
407
+ │ └─ NO → Continue
408
+
409
+ ├─ Does the app need to work offline?
410
+ │ ├─ YES → Offline-first with bidirectional sync
411
+ │ │ │
412
+ │ │ ├─ Can you use a managed sync solution?
413
+ │ │ │ ├─ YES → Firebase Firestore / Realm Sync / PowerSync
414
+ │ │ │ └─ NO → Custom sync engine with conflict resolution
415
+ │ │ │
416
+ │ │ └─ What conflict resolution do you need?
417
+ │ │ ├─ Single-user, rare conflicts → Last Write Wins
418
+ │ │ ├─ Multi-user, structured data → Field-level merge
419
+ │ │ ├─ Multi-user, collaborative editing → CRDTs or OT
420
+ │ │ └─ Critical data, no tolerance for loss → Manual resolution
421
+ │ │
422
+ │ └─ NO → Continue
423
+
424
+ ├─ Does the app need real-time updates (< 1 second)?
425
+ │ ├─ YES → WebSocket (foreground) + silent push (background)
426
+ │ └─ NO → Delta sync on app open + silent push trigger
427
+
428
+ └─ How large is the dataset per user?
429
+ ├─ Small (< 10 MB) → Full local replication with delta sync
430
+ ├─ Medium (10-100 MB) → Partial replication (sync rules / subscriptions)
431
+ └─ Large (> 100 MB) → On-demand fetch with LRU cache, no full sync
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Implementation Sketch
437
+
438
+ ### Push Notification Server (Node.js / TypeScript)
439
+
440
+ ```typescript
441
+ // Push notification service with token management and multi-platform delivery
442
+
443
+ interface DeviceToken {
444
+ userId: string;
445
+ token: string;
446
+ platform: 'ios' | 'android';
447
+ createdAt: Date;
448
+ lastUsedAt: Date;
449
+ }
450
+
451
+ interface PushPayload {
452
+ title: string;
453
+ body: string;
454
+ data?: Record<string, string>;
455
+ collapseKey?: string; // Group/replace notifications
456
+ priority: 'high' | 'normal';
457
+ silent?: boolean; // Data-only, no visible notification
458
+ }
459
+
460
+ class PushNotificationService {
461
+ private tokenRegistry: TokenRegistry;
462
+ private apnsClient: APNsClient;
463
+ private fcmClient: FCMClient;
464
+
465
+ async send(userId: string, payload: PushPayload): Promise<DeliveryResult[]> {
466
+ const tokens = await this.tokenRegistry.getTokensForUser(userId);
467
+ const results: DeliveryResult[] = [];
468
+
469
+ for (const token of tokens) {
470
+ try {
471
+ if (token.platform === 'ios') {
472
+ const result = await this.apnsClient.send(token.token, {
473
+ aps: payload.silent
474
+ ? { 'content-available': 1 }
475
+ : { alert: { title: payload.title, body: payload.body }, sound: 'default' },
476
+ ...payload.data,
477
+ });
478
+ results.push({ token: token.token, status: 'delivered' });
479
+ } else {
480
+ const result = await this.fcmClient.send({
481
+ token: token.token,
482
+ ...(payload.silent
483
+ ? { data: payload.data }
484
+ : {
485
+ notification: { title: payload.title, body: payload.body },
486
+ data: payload.data,
487
+ }),
488
+ android: {
489
+ priority: payload.priority,
490
+ ...(payload.collapseKey && { collapseKey: payload.collapseKey }),
491
+ },
492
+ });
493
+ results.push({ token: token.token, status: 'delivered' });
494
+ }
495
+
496
+ await this.tokenRegistry.updateLastUsed(token.token);
497
+ } catch (error) {
498
+ if (this.isInvalidTokenError(error)) {
499
+ // Token is stale — remove from registry
500
+ await this.tokenRegistry.removeToken(token.token);
501
+ results.push({ token: token.token, status: 'token_removed' });
502
+ } else {
503
+ results.push({ token: token.token, status: 'failed', error });
504
+ }
505
+ }
506
+ }
507
+
508
+ return results;
509
+ }
510
+
511
+ // Periodic cleanup: remove tokens not seen in 60 days
512
+ async pruneStaleTokens(): Promise<number> {
513
+ const cutoff = new Date(Date.now() - 60 * 24 * 60 * 60 * 1000);
514
+ return this.tokenRegistry.removeTokensOlderThan(cutoff);
515
+ }
516
+
517
+ private isInvalidTokenError(error: any): boolean {
518
+ // APNs: 410 Gone, FCM: NotRegistered
519
+ return error.statusCode === 410 || error.code === 'messaging/registration-token-not-registered';
520
+ }
521
+ }
522
+ ```
523
+
524
+ ### Sync Engine (Mobile Client — Pseudocode)
525
+
526
+ ```
527
+ class SyncEngine {
528
+ localDB: LocalDatabase
529
+ remoteAPI: RemoteAPI
530
+ syncCheckpoint: SyncCheckpoint // Persisted lastSyncTimestamp or sequence number
531
+
532
+ // Called on app open, after silent push, or by periodic background task
533
+ async performSync():
534
+ // 1. UPLOAD: Push local changes to server
535
+ pendingChanges = localDB.getRecordsBySyncStatus(['pending_create', 'pending_update', 'pending_delete'])
536
+
537
+ for change in pendingChanges:
538
+ try:
539
+ if change.syncStatus == 'pending_create':
540
+ serverRecord = remoteAPI.create(change.data)
541
+ localDB.updateRecord(change.localId, {
542
+ id: serverRecord.id,
543
+ syncStatus: 'synced',
544
+ serverModifiedAt: serverRecord.updatedAt
545
+ })
546
+
547
+ elif change.syncStatus == 'pending_update':
548
+ serverRecord = remoteAPI.update(change.id, change.data, change.version)
549
+ localDB.updateRecord(change.localId, {
550
+ syncStatus: 'synced',
551
+ serverModifiedAt: serverRecord.updatedAt,
552
+ version: serverRecord.version
553
+ })
554
+
555
+ elif change.syncStatus == 'pending_delete':
556
+ remoteAPI.delete(change.id)
557
+ localDB.hardDelete(change.localId)
558
+
559
+ catch ConflictError as e:
560
+ // Server has a newer version — conflict detected
561
+ serverVersion = e.serverRecord
562
+ localDB.updateRecord(change.localId, {
563
+ syncStatus: 'conflicted',
564
+ conflictData: serverVersion
565
+ })
566
+ // Notify UI to show conflict resolution dialog or auto-resolve
567
+
568
+ catch NetworkError:
569
+ // Leave as pending, will retry on next sync
570
+ break // Stop upload, no point trying more if network is down
571
+
572
+ // 2. DOWNLOAD: Pull server changes since last sync
573
+ cursor = syncCheckpoint.get()
574
+
575
+ while true:
576
+ response = remoteAPI.getChanges(since: cursor, limit: 100)
577
+
578
+ localDB.transaction {
579
+ for record in response.changes:
580
+ existingLocal = localDB.getByServerId(record.id)
581
+
582
+ if existingLocal == null:
583
+ // New record from server
584
+ localDB.insert({
585
+ id: record.id,
586
+ localId: generateUUID(),
587
+ data: record.data,
588
+ syncStatus: 'synced',
589
+ serverModifiedAt: record.updatedAt
590
+ })
591
+
592
+ elif existingLocal.syncStatus == 'synced':
593
+ // No local changes — safe to overwrite
594
+ localDB.updateRecord(existingLocal.localId, {
595
+ data: record.data,
596
+ serverModifiedAt: record.updatedAt,
597
+ version: record.version
598
+ })
599
+
600
+ elif existingLocal.syncStatus in ['pending_update', 'pending_delete']:
601
+ // Local has unsynced changes — conflict
602
+ localDB.updateRecord(existingLocal.localId, {
603
+ syncStatus: 'conflicted',
604
+ conflictData: record.data
605
+ })
606
+
607
+ syncCheckpoint.set(response.cursor)
608
+ }
609
+
610
+ if not response.hasMore:
611
+ break
612
+
613
+ // Called when user modifies a record
614
+ onUserModify(localId, newData):
615
+ localDB.updateRecord(localId, {
616
+ data: newData,
617
+ syncStatus: 'pending_update',
618
+ localModifiedAt: now()
619
+ })
620
+ scheduleSyncDebounced(delay: 2_seconds)
621
+
622
+ // Called when user creates a record
623
+ onUserCreate(data):
624
+ localId = generateUUID()
625
+ localDB.insert({
626
+ id: null, // No server ID yet
627
+ localId: localId,
628
+ data: data,
629
+ syncStatus: 'pending_create',
630
+ localModifiedAt: now()
631
+ })
632
+ scheduleSyncDebounced(delay: 2_seconds)
633
+ }
634
+ ```
635
+
636
+ ### Background Sync Registration (iOS — Swift)
637
+
638
+ ```swift
639
+ // AppDelegate — register background tasks
640
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
641
+
642
+ // Register periodic sync task
643
+ BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.app.sync", using: nil) { task in
644
+ self.handleBackgroundSync(task: task as! BGAppRefreshTask)
645
+ }
646
+
647
+ return true
648
+ }
649
+
650
+ func applicationDidEnterBackground(_ application: UIApplication) {
651
+ scheduleBackgroundSync()
652
+ }
653
+
654
+ func scheduleBackgroundSync() {
655
+ let request = BGAppRefreshTaskRequest(identifier: "com.app.sync")
656
+ request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // No sooner than 15 min
657
+ try? BGTaskScheduler.shared.submit(request)
658
+ }
659
+
660
+ func handleBackgroundSync(task: BGAppRefreshTask) {
661
+ // Schedule the next sync before starting this one
662
+ scheduleBackgroundSync()
663
+
664
+ let syncOperation = SyncEngine.shared.performSync()
665
+
666
+ task.expirationHandler = {
667
+ syncOperation.cancel()
668
+ }
669
+
670
+ syncOperation.onComplete { success in
671
+ task.setTaskCompleted(success: success)
672
+ }
673
+ }
674
+
675
+ // Handle silent push
676
+ func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
677
+
678
+ SyncEngine.shared.performSync { result in
679
+ switch result {
680
+ case .newData: completionHandler(.newData)
681
+ case .noData: completionHandler(.noData)
682
+ case .failed: completionHandler(.failed)
683
+ }
684
+ }
685
+ }
686
+ ```
687
+
688
+ ### Background Sync Registration (Android — Kotlin)
689
+
690
+ ```kotlin
691
+ // Schedule periodic sync with WorkManager
692
+ class SyncScheduler {
693
+ fun schedulePeriodicSync(context: Context) {
694
+ val constraints = Constraints.Builder()
695
+ .setRequiredNetworkType(NetworkType.CONNECTED)
696
+ .setRequiresBatteryNotLow(true)
697
+ .build()
698
+
699
+ val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(
700
+ repeatInterval = 15, repeatIntervalTimeUnit = TimeUnit.MINUTES
701
+ )
702
+ .setConstraints(constraints)
703
+ .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
704
+ .build()
705
+
706
+ WorkManager.getInstance(context).enqueueUniquePeriodicWork(
707
+ "data_sync",
708
+ ExistingPeriodicWorkPolicy.KEEP, // Don't replace if already scheduled
709
+ syncRequest
710
+ )
711
+ }
712
+ }
713
+
714
+ // SyncWorker — performs the actual sync
715
+ class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
716
+ override suspend fun doWork(): Result {
717
+ return try {
718
+ val syncEngine = SyncEngine.getInstance(applicationContext)
719
+ syncEngine.performSync()
720
+ Result.success()
721
+ } catch (e: Exception) {
722
+ if (runAttemptCount < 3) Result.retry() else Result.failure()
723
+ }
724
+ }
725
+ }
726
+
727
+ // Handle FCM data message (silent push)
728
+ class SyncMessagingService : FirebaseMessagingService() {
729
+ override fun onMessageReceived(message: RemoteMessage) {
730
+ if (message.data.containsKey("sync_trigger")) {
731
+ // Enqueue one-time sync
732
+ val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
733
+ .setConstraints(Constraints.Builder()
734
+ .setRequiredNetworkType(NetworkType.CONNECTED)
735
+ .build())
736
+ .build()
737
+ WorkManager.getInstance(this).enqueue(syncRequest)
738
+ }
739
+ }
740
+
741
+ override fun onNewToken(token: String) {
742
+ // Token refreshed — send to server
743
+ CoroutineScope(Dispatchers.IO).launch {
744
+ ApiClient.registerDeviceToken(token, platform = "android")
745
+ }
746
+ }
747
+ }
748
+ ```
749
+
750
+ ---
751
+
752
+ ## Cross-References
753
+
754
+ - **[offline-first](../patterns/offline-first.md)** — Offline-first architecture patterns that build on the sync foundations described here
755
+ - **[mobile-app-architecture](./mobile-app-architecture.md)** — Broader mobile architecture patterns including the data layer where sync engines live
756
+ - **[websockets-realtime](../integration/websockets-realtime.md)** — Deep dive into WebSocket connection management, scaling, and protocol details
757
+ - **[mobile-backend-for-frontend](./mobile-backend-for-frontend.md)** — BFF pattern for mobile APIs, including how sync endpoints are designed differently from standard REST
758
+
759
+ ---
760
+
761
+ ## Sources
762
+
763
+ - [FCM Architectural Overview — Firebase](https://firebase.google.com/docs/cloud-messaging/fcm-architecture)
764
+ - [How Push Notification Delivery Works Internally — Clix](https://blog.clix.so/how-push-notification-delivery-works-internally/)
765
+ - [Push Notifications Deep Dive: APNs & FCM — Spritle](https://www.spritle.com/blog/push-notifications-deep-dive-the-ultimate-technical-guide-to-apns-fcm/)
766
+ - [How to Design a Notification System — System Design Handbook](https://www.systemdesignhandbook.com/guides/design-a-notification-system/)
767
+ - [Push Notification Statistics 2025 — Business of Apps](https://www.businessofapps.com/marketplace/push-notifications/research/push-notifications-statistics/)
768
+ - [50+ Push Notification Statistics 2025 — MobiLoud](https://www.mobiloud.com/blog/push-notification-statistics)
769
+ - [Why People Are Turning Off Push — Andrew Chen](https://andrewchen.com/why-people-are-turning-off-push/)
770
+ - [How Figma's Multiplayer Technology Works — Figma Blog](https://www.figma.com/blog/how-figmas-multiplayer-technology-works/)
771
+ - [Understanding Sync Engines: Figma, Linear, Google Docs — Liveblocks](https://liveblocks.io/blog/understanding-sync-engines-how-figma-linear-and-google-docs-work)
772
+ - [Offline-First Architecture: Syncing, Caching, and Conflict Resolution — Medium](https://medium.com/@dadaodunayo6/offline-first-mobile-app-architecture-syncing-caching-and-conflict-resolution-27a4e7b10162)
773
+ - [Complete Guide to Offline-First Architecture in Android — droidcon](https://www.droidcon.com/2025/12/16/the-complete-guide-to-offline-first-architecture-in-android/)
774
+ - [Firebase vs OneSignal Comparison — Ably](https://ably.com/compare/firebase-vs-onesignal)
775
+ - [FCM vs OneSignal Push Comparison — Courier](https://www.courier.com/integrations/compare/firebase-fcm-vs-onesignal-push)
776
+ - [BGTaskScheduler — Apple Developer Documentation](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler)
777
+ - [WorkManager Background Task Scheduling — Android Developers](https://developer.android.com/topic/libraries/architecture/workmanager)
778
+ - [WebSockets vs SSE — Ably](https://ably.com/blog/websockets-vs-sse)
779
+ - [Best Practices for FCM Token Management — Firebase](https://firebase.google.com/docs/cloud-messaging/manage-tokens)
780
+ - [Understanding FCM Message Delivery on Android — Firebase Blog](https://firebase.blog/posts/2024/07/understand-fcm-delivery-rates/)
781
+ - [Designing a Real-Time Chat App — Design Gurus](https://www.designgurus.io/blog/design-chat-application)
782
+ - [Real-Time Data Synchronization in Mobile Apps — Zetaton](https://www.zetaton.com/blogs/real-time-data-synchronization-in-mobile-apps)