☁️ 2.6 Persistance cloud et Backend-as-a-Service (BaaS)

Module 335 – Réaliser une application pour mobile

🎯 Objectif d'apprentissage

À la fin de ce chapitre, vous serez capables de :

  • Expliquer ce qu’est un Backend-as-a-Service (BaaS) et pourquoi il facilite le développement mobile

  • Comprendre l’intérêt du cloud dans une application moderne

  • Faire la différence entre Supabase, Firebase, Appwrite, AWS Amplify, etc.

  • Gérer des données distantes (CRUD), la synchro cloud ↔ local et la gestion des permissions

  • Intégrer dans une app mobile :

    • une base de données distante
    • du stockage de fichiers
    • des fonctions serverless
    • des notifications push
    • une authentification utilisateur

🤔 2.6.1 Introduction : pourquoi un backend cloud ?

Les applications mobiles modernes doivent :

  • synchroniser des données entre appareils
  • gérer des profils utilisateurs
  • fonctionner de manière fluide sur plusieurs appareils

Cela implique généralement :

  • une base de données distante
  • une API (lectures / écritures)
  • une authentification
  • du stockage de fichiers (images, PDF…)
  • des fonctions serveur
  • une gestion des permissions

2.6.1 Problème sans BaaS

Créer tout cela à la main signifie :

  • gérer un serveur (hébergement, OS, mises à jour)
  • coder une API (REST / GraphQL)
  • assurer la sécurité (auth, permissions, protections)
  • gérer la scalabilité (beaucoup d’utilisateurs ?)
  • maintenir le tout dans le temps

💥 Résultat : long, coûteux, complexe… surtout pour un projet mobile “simple”.

2.6.1 Ce qu’apporte un backend cloud

Un backend cloud apporte :

  • Stockage et sauvegarde automatiques des données
  • Données accessibles depuis n’importe quel appareil
  • Mises à jour instantanées via des API
  • Automatisation du “travail serveur” : → authentification, règles de sécurité, fichiers, logs, etc.
  • Aucune gestion directe de : → serveurs, mises à l’échelle, monitoring bas niveau

💡 Pour un module pédagogique ou une app interne, un BaaS est souvent le meilleur compromis.

2.6.1 Exemple concret

Exemple : une app où des élèves stockent leurs notes et photos de projets.

  • L’élève change de téléphone
  • Il se reconnecte
  • ✅ Toutes ses données sont déjà là : stockées dans le cloud

🏭 2.6.2 Qu’est-ce qu’un Backend-as-a-Service (BaaS) ?

Un BaaS = un backend prêt à l’emploi, hébergé dans le cloud.

Il fournit les briques principales d’un backend moderne, sans :

  • installer de serveur
  • configurer un environnement
  • coder soi-même toutes les API

2.6.2 Ce qu’un BaaS fournit généralement

  • 🔏 Authentification (email, OAuth, social login, magic link, etc.)
  • 🗄️ Base de données distante (SQL ou NoSQL)
  • 🖼️ Stockage de fichiers (images, vidéos, PDF, etc.)
  • 🌐 API générée automatiquement
  • ⚙️ Fonctions serverless (exécution de code côté serveur)
  • 🔔 Notifications push
  • 🛡️ Gestion des rôles / permissions
  • 📊 Logs & analytics

2.6.2 Avantages d’un BaaS

  • Aucune infrastructure à gérer (backups, patchs, sécurité bas niveau)

  • Développement rapide grâce aux SDK et API prêtes à l’emploi

  • Sécurité intégrée : permissions, règles d’accès, JWT, etc.

  • Scalabilité automatique (le service s’adapte à la charge)

  • Particulièrement adapté aux apps mobiles :

    • data synchronisée
    • auth utilisateurs
    • fichiers

2.6.2 Limites d’un BaaS

  • Dépendance au fournisseur (vendor lock-in)

  • Coûts qui peuvent augmenter avec :

    • le nombre d’utilisateurs
    • le volume de données
    • les requêtes réseau
  • Moins flexible qu’un backend 100 % sur mesure

💬 Dans un contexte pédagogique ou de projet interne, ces limites sont souvent acceptables.

🧱 2.6.3 Comment fonctionne une base cloud ?

Cycle classique d’un échange entre une app mobile et un backend cloud :

  1. Authentification (login, tokens)
  2. Requêtes signées (headers avec token)
  3. Application des permissions côté backend
  4. Réponse JSON
  5. Mise à jour du stockage local
  6. Gestion du mode offline + synchronisation

2.6.3 Étape 1 – L’utilisateur se connecte

L’utilisateur saisit : email + mot de passe (ou Google, Apple, etc.).

L’app envoie ces infos au backend :

POST /auth/v1/token HTTP/1.1
Host: api.mon-backend.com
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "super-secret"
}

Le backend :

  • vérifie les identifiants

  • génère un JWT (JSON Web Token) avec :

    • user_id
    • rôles / permissions
    • date d’expiration

2.6.3 Étape 1 – Stockage du token

L’app stocke ensuite le token dans un stockage sécurisé :

// Exemple pseudo-code avec SecureStorage
await SecureStorage.set({
  key: 'access_token',
  value: jwtToken
})

🔐 À partir de là, l’app n’envoie plus le mot de passe, uniquement le token à chaque requête.

2.6.3 Étape 2 – L’app envoie une requête au backend

À chaque appel au backend, l’app ajoute :

GET /rest/v1/notes HTTP/1.1
Host: api.mon-backend.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

En TypeScript (Ionic + fetch) :

const token = await SecureStorage.get({ key: 'access_token' })

const res = await fetch('https://api.mon-backend.com/rest/v1/notes', {
  headers: {
    Authorization: `Bearer ${token.value}`,
    'Content-Type': 'application/json'
  }
})

const data = await res.json()

2.6.3 Étape 3 – Permissions côté backend

Côté backend, pour chaque requête :

  1. Vérification du token (signature, expiration)

  2. Lecture des claims (ex. user_id, role)

  3. Application des règles de sécurité :

    • l’utilisateur peut-il lire ces données ?
    • a-t-il le droit de modifier cet élément ?
    • est-il propriétaire de la ressource ?

Exemple de règle (pseudo-SQL) :

-- Un utilisateur ne peut lire que ses propres notes
SELECT * FROM notes
WHERE user_id = auth.uid();

Si la permission est refusée → 401 ou 403.

2.6.3 Étape 4 – Réponse JSON

Si tout est OK, le backend renvoie un JSON adapté à l’utilisateur.

Exemple Supabase :

GET /rest/v1/notes?user_id=eq.214 HTTP/1.1
Host: xyz.supabase.co
Authorization: Bearer <token>
apikey: <public-anon-key>

Réponse :

[
  {
    "id": 42,
    "user_id": 214,
    "title": "Note de cours",
    "content": "Backend as a Service",
    "created_at": "2025-11-19T10:15:00Z"
  }
]

L’app :

  • reçoit ce JSON
  • met à jour son store / composants

2.6.3 Étape 5 – Mise à jour de la base locale

Pour un usage fluide et offline-first, l’app garde une copie locale :

  • base locale (SQLite, IndexedDB, Hive, etc.)
  • et/ou store (Pinia, Redux) persisté

Exemple pseudo-code (Pinia) :

const useNotesStore = defineStore('notes', {
  state: () => ({
    notes: [] as Note[]
  }),
  actions: {
    async fetchNotes() {
      const token = await SecureStorage.get({ key: 'access_token' })
      const res = await fetch('https://api.mon-backend.com/rest/v1/notes', {
        headers: { Authorization: `Bearer ${token.value}` }
      })
      this.notes = await res.json()
      // TODO: sauvegarder aussi en local (SQLite / Capacitor Storage)
    }
  }
})

✅ Interface réactive et responsive, même après redémarrage.

2.6.3 Étape 6 – Offline + synchronisation

Quand l’app est hors ligne :

  • les actions utilisateur sont stockées localement (queue)

  • exemples :

    • CREATE_NOTE
    • UPDATE_NOTE
    • DELETE_NOTE

Exemple de type :

type PendingAction = {
  type: 'CREATE_NOTE' | 'UPDATE_NOTE' | 'DELETE_NOTE'
  payload: any
  createdAt: string
}

La queue peut être stockée :

  • en table locale (SQLite)
  • en fichier
  • ou en storage clé–valeur

2.6.3 Étape 6 – Replay de la queue

Dès que la connexion revient :

  1. l’app envoie les actions de la queue au backend
  2. supprime celles qui ont réussi
  3. récupère une version à jour des données

💡 Même modèle que l’on utilise avec Supabase, Firebase, Appwrite, etc. Auth → token → requêtes signées → règles de sécurité → JSON → cache local → sync offline.

⚡ 2.6.4 Supabase – une plateforme SQL moderne et ouverte

Supabase = BaaS construit autour de PostgreSQL.

Objectif : une alternative open-source aux solutions propriétaires, basée sur des standards :

  • SQL
  • REST
  • JWT
  • permissions explicites

2.6.4 Supabase – Base de données SQL prête à l’emploi

Supabase repose sur PostgreSQL :

  • données structurées dans des tables

  • relations, contraintes, clés étrangères

  • idéal pour des données cohérentes et liées :

    • profils
    • notes
    • projets
    • documents

Supabase génère automatiquement :

  • une API REST pour chaque table

  • une API GraphQL (optionnelle)

  • une console web pour :

    • gérer données
    • configurer permissions
    • voir les logs

2.6.4 Supabase – Authentification & permissions

Supabase propose un système d’auth complet :

  • Email / mot de passe
  • OAuth (Google, GitHub, etc.)
  • Magic links

Les règles de sécurité sont basées sur Row Level Security (RLS) :

Les RLS permettent de définir qui peut lire / écrire quelle ligne dans une table, en fonction :

  • de l’utilisateur connecté
  • de son rôle
  • du contexte (auth.uid()…)

2.6.4 Supabase – Stockage de fichiers

Supabase inclut un service de stockage de fichiers :

  • images
  • PDF
  • vidéos
  • autres médias

Organisation en buckets (comme Amazon S3).

L’accès aux fichiers suit :

  • les mêmes logiques de permissions
  • que la base de données (policies, RLS, etc.)

2.6.4 Supabase – Temps réel & Edge Functions

Supabase intègre :

  • un système realtime (basé sur PostgreSQL) :

    • écoute des insertions / mises à jour / suppressions
  • des Edge Functions (fonctions serverless) pour :

    • envoyer des emails
    • traiter des images
    • appliquer de la logique côté serveur

Permet de créer des interactions dynamiques dans l’app mobile.

2.6.4 Supabase – Pourquoi c’est pertinent en cours

L’approche SQL permet d’apprendre :

  • les bases du backend sans gérer de serveur
  • le langage SQL
  • le lien API ↔ base de données
  • les systèmes d’authentification modernes
  • la sécurité (RLS, JWT, permissions)
  • la synchronisation cloud pour mobile

2.6.4 Supabase – Exemple d’insertion

const { data, error } = await supabase
  .from('notes')
  .insert([
    { user_id: '214', title: 'Note de cours', content: 'Contenu de la note' }
  ])

🎯 Une seule instruction côté client → Supabase gère l’auth, la permission, l’écriture en base, et le retour JSON.

🔥 2.6.5 Firebase – solution NoSQL simple & temps réel

Firebase = plateforme BaaS de Google.

Points forts :

  • intégration rapide
  • SDK très simples
  • synchronisation temps réel multi-appareils

2.6.5 Firebase – Stockage NoSQL

Deux systèmes principaux :

  • Firestore → collections & documents
  • Realtime Database → noeuds JSON synchronisés en direct

Ce modèle NoSQL est :

  • très flexible

  • sans relations strictes (comme en SQL)

  • performant pour :

    • chat
    • présence en ligne
    • collaboration temps réel

2.6.5 Firebase – Temps réel

Lorsque des données changent :

  • tous les clients abonnés reçoivent la mise à jour
  • en quelques millisecondes

Idéal pour :

  • messageries
  • outils collaboratifs
  • interfaces interactives en direct

2.6.5 Firebase – Auth intégrée

Firebase propose :

  • email / mot de passe
  • téléphone (SMS OTP)
  • comptes Google, Apple, GitHub, etc.

Sessions :

  • gérées automatiquement par les SDK
  • persistance simplifiée

2.6.5 Firebase – Stockage de fichiers

Firebase propose :

  • Cloud Storage pour images, vidéos, docs
  • règles de sécurité liées au module Auth

🎯 Très pratique pour des apps simples qui doivent stocker des médias utilisateur.

2.6.5 Firebase – Quand le choisir ?

Firebase est particulièrement adapté :

  • aux projets éducatifs
  • aux prototypes rapides
  • aux apps collaboratives / temps réel
  • aux équipes cherchant une solution très simple à intégrer

2.6.5 Firebase – Points d’attention

Le NoSQL nécessite :

  • un modèle de données réfléchi

  • éviter :

    • duplications abusives
    • requêtes complexes difficiles à maintenir
    • coûts surprises (lecture / écriture répétées)

💬 Firebase convient mieux aux données peu structurées ou très dynamiques.

⚖️ 2.6.6 Supabase vs Firebase

Deux approches :

  • Supabase → SQL, standards ouverts
  • Firebase → NoSQL, simplicité, temps réel

Les deux offrent :

  • Auth
  • Storage
  • Fonctions serverless
  • Realtime

Mais la philosophie est différente.

2.6.6 Supabase vs Firebase – Philosophies

  • Supabase → structure relationnelle, claire, avec contraintes → idéal pour applications avec modèle de données structuré

  • Firebase → documents & collections, très flexible → idéal pour données désynchronisées, temps réel

2.6.6 Tableau comparatif

Critère Supabase Firebase
Type de base Relationnelle (PostgreSQL) NoSQL (Firestore) – Documents / Collections
API REST + GraphQL natifs SDK propriétaires uniquement
Auth JWT, flexible (Email, OAuth, Magic Links) Auth Google (simple / robuste), Email, téléphone, social
Realtime Oui Oui (très optimisé)
Storage Buckets type S3 Cloud Storage
Open-source Oui Non
Facile pour débutants ⭐⭐⭐ ⭐⭐⭐⭐⭐
Pertinence pédagogique ⭐⭐⭐⭐⭐ (concepts universels) ⭐⭐ (NoSQL uniquement)
Idéal pour… projets structurés, SQL prototypes, apps temps réel

💬 En résumé

  • Firebase : parfait pour démarrer vite, temps réel, concepts NoSQL.
  • Supabase : idéal pour apprendre SQL + API REST + sécurité.

💭 2.6.7 Autres solutions BaaS populaires

☁️ Appwrite

  • BaaS open-source
  • Base NoSQL
  • Auth complète
  • Stockage de fichiers
  • Fonctions serverless
  • Interface d’admin web

✅ Souvent auto-hébergé → contrôle total des données.

2.6.7 AWS Amplify

Solution BaaS d’AWS :

  • Base : DynamoDB
  • Auth : Cognito
  • Storage : S3
  • Fonctions : Lambda
    • outils de déploiement

⚠️ Puissant mais parfois complexe pour un débutant. Idéal pour projets à forte scalabilité dans l’écosystème AWS.

2.6.7 Backendless

Backendless propose :

  • base de données relationnelle
  • authentification
  • stockage de fichiers
  • fonctions serverless
  • notifications push

Atouts :

  • interface graphique conviviale
  • nombreuses options de personnalisation

🎯 Adapté à ceux qui veulent une solution complète avec UI d’admin riche.

2.6.7 Back4app

Back4app (basé sur Parse Server) propose :

  • base NoSQL
  • authentification
  • stockage de fichiers
  • fonctions serverless
  • notifications push

Atouts :

  • simplicité d’utilisation
  • modèle de tarification flexible

🎯 Intéressant si vous aimez l’approche Parse et une doc accessible.

🔄️ 2.6.8 Synchronisation cloud ↔ local

La synchronisation entre :

  • stockage local (chapitre 2.4)
  • backend cloud (chapitre 2.6)

est centrale pour une app mobile moderne.

🎯 Objectif : Offrir une expérience fluide, continue, fiable, même avec un réseau instable.

2.6.8 Pourquoi synchroniser ?

Parce que les données doivent être :

  • accessibles hors ligne
  • sauvegardées sur un serveur
  • partageables entre plusieurs appareils
  • aussi à jour que possible

Exemple : une app de notes avec sync entre smartphone, tablette et web.

2.6.8 Exemple – App de notes

  • L’app utilise SQLite pour enregistrer une note hors-ligne

  • Lorsque la connexion revient :

    • la note est envoyée vers Supabase / Firebase
    • la base cloud se met à jour
    • les autres appareils peuvent récupérer la nouvelle note

2.6.8 Workflow standard de synchro

  1. Lecture initiale depuis le stockage local
  2. Mise à jour silencieuse depuis le cloud
  3. Queue locale d’actions hors-ligne
  4. Synchronisation automatique quand le réseau revient
  5. Gestion des conflits (local vs cloud)

2.6.8 Étape 1 – Lecture initiale (local)

Au démarrage :

  • l’app charge immédiatement les données locales
  • l’interface est utilisable sans réseau
  • pas besoin d’appeler le cloud pour afficher quelque chose
// Lecture depuis SQLite au démarrage
const notes = await db.selectFrom('notes').selectAll().execute()
store.notes = notes

✅ Ouverture instantanée + fonctionnement offline garanti.

2.6.8 Étape 2 – Mise à jour silencieuse (cloud)

Si le réseau est disponible :

  • l’app récupère les données du backend (Supabase, Firebase…)
  • compare local / distant
  • met à jour la base locale en arrière-plan
const { data } = await supabase
  .from('notes')
  .select('*')
  .eq('user_id', user.id)

await saveToLocalDB(data)

💡 L’UI reste fluide → les nouvelles données remplacent progressivement l’ancien cache.

2.6.8 Étape 3 – File d’attente offline (queue)

Quand l’utilisateur agit sans réseau :

  • crée une note
  • modifie une tâche
  • supprime un élément

L’app :

  1. met à jour les données en local
  2. ajoute l’action dans une queue locale
type PendingAction = {
  id: string
  type: 'CREATE_NOTE' | 'UPDATE_NOTE' | 'DELETE_NOTE'
  payload: any
  timestamp: number
}

🧠 La queue mémorise “ce que l’utilisateur voulait faire”.

2.6.8 Étape 4 – Sync automatique au retour du réseau

Avec Capacitor (Ionic) :

import { Network } from '@capacitor/network'

Network.addListener('networkStatusChange', status => {
  if (status.connected) {
    syncPendingActions()
  }
})

Fonction de synchronisation :

async function syncPendingActions() {
  for (const action of queue) {
    await sendToBackend(action)
    markActionSynced(action.id)
  }
}

💡 Synchronisation automatique et silencieuse.

2.6.8 Étape 5 – Gestion des conflits

Conflit = même donnée modifiée :

  • en local hors-ligne
  • et sur le cloud, par un autre appareil

Stratégies :

  • Last Write Wins (le plus récent gagne)
  • Serveur prioritaire
  • Local prioritaire (cas d’un brouillon)
  • Merge logique (textes, documents collaboratifs)

2.6.8 Exemple de résolution simplifiée

if (local.updated_at > remote.updated_at) {
  // garder la version locale
  upload(local)
} else {
  // garder la version cloud
  saveToLocalDB(remote)
}

🧩 Le choix dépend du type d’application (notes, todo, documents, finances, etc.).

2.6.8 Bonus – Comment Ionic-Vue détecte la connectivité

Une app offline-first ne “poll” pas le réseau.

Avec Ionic-Vue + Capacitor Network :

  1. état réseau au démarrage
  2. événements envoyés par l’OS (online / offline)

🎯 L’app réagit aux changements de réseau, elle ne les surveille pas en boucle.

2.6.8 Détection au démarrage

import { Network } from '@capacitor/network'

const status = await Network.getStatus()
console.log('Connected at startup:', status.connected)

if (!status.connected) {
  enterOfflineMode()
}

Exemple de sortie :

{
  "connected": false,
  "connectionType": "none"
}

L’app sait tout de suite si elle doit charger :

  • uniquement les données locales (offline)
  • ou lancer une synchronisation cloud

2.6.8 Événements réseau

iOS / Android envoient des événements :

  • “offline”
  • “Wi-Fi connecté”
  • “4G/5G active”
  • “réseau revenu”
import { Network } from '@capacitor/network'

Network.addListener('networkStatusChange', status => {
  console.log('Network changed:', status)

  if (status.connected) {
    syncPendingActions()
  } else {
    enterOfflineMode()
  }
})

C’est l’OS qui prévient l’app, pas l’inverse.

2.6.8 Gestion de la queue offline (rappel)

type PendingAction = {
  id: string
  type: 'CREATE' | 'UPDATE' | 'DELETE'
  payload: any
  timestamp: number
}

let queue: PendingAction[] = []

export function addOfflineAction(action: PendingAction) {
  queue.push(action)
  // TODO : sauvegarder en SQLite ou Capacitor Preferences
}

Puis :

// Exemple lorsqu’une note est éditée hors-ligne
addOfflineAction({
  id: crypto.randomUUID(),
  type: 'UPDATE',
  payload: { id: 42, title: 'Nouvelle valeur' },
  timestamp: Date.now()
})

L’UI se met à jour immédiatement → la sync viendra plus tard.

2.6.8 Sync quand le réseau revient (rappel)

async function syncPendingActions() {
  for (const action of queue) {
    await sendToBackend(action) // requête API
    action.synced = true
  }

  // Nettoyage de la queue
  queue = queue.filter(a => !a.synced)
}

✅ L’utilisateur ne fait rien. La synchronisation est automatique et fiable.

2.6.8 Résumé – Offline-first et BaaS

  • L’app récupère l’état réseau initial

  • L’OS signale les changements (online / offline)

  • Les actions offline vont dans une queue

  • Quand le réseau revient :

    • les actions sont rejouées
    • la queue est nettoyée
    • le cloud et le local sont resynchronisés

🎯 Modèle utilisé par : WhatsApp, Notion, Google Drive, etc.

🔗 2.6.10 Références et ressources

☁️ 2.6 Persistance cloud et Backend-as-a-Service (BaaS)

By tirtho

☁️ 2.6 Persistance cloud et Backend-as-a-Service (BaaS)

  • 26