Backend APIs for Mobile Apps

Building Backend APIs for Mobile Apps (iOS, Android, Flutter) on DomainIndia Hosting

By Domain India Team · DomainIndia EngineeringPublished · Updated 7 min read
Knowledge base article
Contents (14 sections)
TL;DR

Mobile apps need a backend. This guide covers REST vs GraphQL for mobile, authentication (JWT, OAuth, biometric), push notifications (FCM + APNs), file uploads, offline sync, and choosing the right DomainIndia hosting tier for your app's stage.

What mobile backends must handle

Every mobile app (iOS, Android, React Native, Flutter) talks to a backend for:

  • User signup / login (email, Google, Apple, phone OTP)
  • Content feeds — loaded lazily, paginated
  • File uploads (profile photos, documents, audio)
  • Push notifications
  • Real-time updates (chat, live scores, order tracking)
  • Analytics events
  • Payments (Razorpay/Stripe for Indian + global markets)
  • Offline sync (app works without internet, syncs on reconnect)

Which DomainIndia plan?

App stageMAU (monthly active users)Recommended plan
Prototype / testing<1,000Shared cPanel with Node.js or Laravel
MVP / growing1,000 – 10,000VPS Starter (2 GB)
Production / scaling10,000 – 100,000VPS Business (4 GB) + Cloudflare CDN
High-scale100,000+Multi-VPS + load balancer + managed PostgreSQL

Mobile backends are API-only (no HTML rendering), so they're efficient. A 2 GB VPS easily handles 10,000 MAU for a typical social/commerce app.

Choosing the API style

REST — simple, works everywhere, easy caching. Best default.

GraphQL — thin clients love minimal payloads over 3G. See our GraphQL APIs article.

gRPC — internal microservices; rarely used client-side for mobile (except streaming/IoT).

WebSockets / Server-Sent Events — real-time (chat, live trackers).

For most Indian apps: REST with JSON + WebSockets for real-time features. Add GraphQL only if you have multiple mobile platforms with different field needs.

Authentication patterns

Pattern 1 — JWT with refresh tokens

Classic for mobile. Apps can't keep a cookie-based session easily.

  1. User logs in with email + password (or social OAuth)
  2. Backend issues:
    • Short-lived access token (15 min)
    • Long-lived refresh token (30 days), stored encrypted on device
  3. Every API call sends Authorization: Bearer <access_token>
  4. Before expiry, app POSTs refresh token → gets new access token
  5. Refresh token can be revoked server-side (logout all devices)

Node.js example:

javascript
import jwt from 'jsonwebtoken';

function issueTokens(userId) {
  const accessToken = jwt.sign({ sub: userId }, ACCESS_SECRET, { expiresIn: '15m' });
  const refreshToken = jwt.sign({ sub: userId, type: 'refresh' }, REFRESH_SECRET, { expiresIn: '30d' });
  // Store hash of refresh token in DB for revocation
  db.refreshToken.create({ userId, hash: sha256(refreshToken), expiresAt: ... });
  return { accessToken, refreshToken };
}

// Client calls POST /auth/refresh with the refresh token:
app.post('/auth/refresh', async (req, res) => {
  const { refreshToken } = req.body;
  const payload = jwt.verify(refreshToken, REFRESH_SECRET);
  const stored = await db.refreshToken.findFirst({ where: { hash: sha256(refreshToken) } });
  if (!stored || stored.revoked) return res.status(401).json({ error: 'Invalid' });
  res.json(issueTokens(payload.sub));
});

Pattern 2 — OAuth (Sign in with Apple / Google)

Mandatory for iOS apps that offer any other login (App Store rule). Google Sign-In covers Android.

  • iOS: Apple Sign-In, returns identity token, verify signature against Apple's JWK
  • Android: Google Sign-In, same pattern with Google JWK

Your backend stores a provider + providerUserId → internalUserId mapping.

Pattern 3 — Biometric unlock (local)

Device unlocks the refresh token using FaceID / fingerprint, then sends it to your API. Your API doesn't know or care about biometrics — it just sees refresh → access.

Push notifications

Two providers: Firebase Cloud Messaging (FCM) for Android + cross-platform, Apple Push Notification service (APNs) for iOS.

Easiest path: use FCM for both. Firebase handles APNs relay for you.

  1. Create Firebase project, add iOS + Android apps
  2. Download google-services.json (Android) + GoogleService-Info.plist (iOS)
  3. App registers with FCM on first launch → gets device token → POSTs to your /push/register endpoint
  4. Backend stores userId ↔ deviceToken mapping
  5. To notify:
    bash
    curl -X POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT/messages:send 
      -H "Authorization: Bearer $ACCESS_TOKEN" 
      -H "Content-Type: application/json" 
      -d '{"message":{"token":"DEVICE_TOKEN","notification":{"title":"Order shipped","body":"Track now"}}}'

Libraries: firebase-admin (Node), pyfcm (Python), kreait/firebase-php.

File uploads

Mobile devices upload photos, videos, documents. Strategies:

Direct-to-S3 (or Backblaze B2) with presigned URLs — recommended.

  • Client requests POST /upload-url with filename + content-type
  • Backend returns a 10-minute signed URL to upload directly to S3
  • Client PUTs the file to S3; no hop through your API
  • Client notifies backend with the final S3 key

Saves your VPS bandwidth + CPU. Scales infinitely.

Through-your-API upload — only for small files (<5 MB). Simpler but consumes VPS RAM/bandwidth.

javascript
import multer from 'multer';
const upload = multer({ limits: { fileSize: 5 * 1024 * 1024 }, dest: '/tmp/' });
app.post('/upload', upload.single('file'), async (req, res) => {
  const key = `users/${req.user.id}/${Date.now()}-${req.file.originalname}`;
  await s3.putObject({ Bucket: 'uploads', Key: key, Body: fs.createReadStream(req.file.path) });
  res.json({ url: `https://cdn.yourcompany.com/${key}` });
});

Offline sync

Users in India's metro-to-tier-2 transitions (weak 4G, metro tunnels) demand offline-first apps.

Patterns:

  1. Optimistic writes — app writes to local SQLite first, then syncs. Show "syncing..." indicator.
  2. Pull-based sync with timestampsGET /sync?since=<last_sync_at> returns changes. Client applies.
  3. Realm / WatermelonDB / PowerSync — libraries that handle sync for you.

Backend needs:

  • updatedAt timestamp on every row (auto-update on change)
  • Soft deletes (flag deletedAt, don't hard-delete)
  • Tombstone endpoint listing deleted IDs since timestamp

Payments (Indian market)

Primary: Razorpay (UPI, cards, netbanking, wallets, subscriptions). Alternative: Stripe (cards, international).

Mobile integration uses their official SDKs — your backend creates the order on Razorpay API, passes order ID to app, app opens Razorpay Checkout, app sends signature back to backend for verification. See our Razorpay Integration article.

Versioning your API

Mobile apps don't auto-update — expect users running 6-month-old app versions for years.

Pattern: version your API URL (/v1/, /v2/) and keep old versions running indefinitely.

code
GET /v1/feed   # legacy — keep forever
GET /v2/feed   # current
GET /v3/feed   # next

If you can't maintain N versions forever, use feature-flagged responses keyed by the User-Agent or a custom X-App-Version header.

Security essentials

Always HTTPS — no exceptions. Mobile OSes increasingly block cleartext.
Certificate pinning — harder for attackers to MITM your API. OkHttp + URLSession both support it.
Rate limit by device — 100 req/min per device. Prevents abuse.
Never return stack traces — use generic error messages; log details server-side.
Sign API requests — add an HMAC signature using a per-user secret. Stops replay attacks.
OWASP Mobile Top 10 — review annually.

FAQ

Can I host a mobile backend on shared cPanel?

Yes for prototypes and small apps (<1K users). Node.js via Setup Node.js App, or Laravel/Rails for traditional stacks. For serious traffic, upgrade to VPS.

Do I need a separate dev / staging / production?

Yes. Mobile apps can't "hotfix" server bugs — apps run against whatever backend version they target. Never point new app builds at production until tested on staging.

How much does mobile backend cost at 100K users?

Typical stack on DomainIndia: VPS Business (~₹3,000/mo) + PostgreSQL managed or self-hosted + S3-compatible storage (~₹500/mo) + Cloudflare Free + FCM Free = ~₹4,000/mo total. Scales linearly with active usage.

React Native vs Flutter vs native — does the backend change?

No. Your API is stack-agnostic. Pick frontend based on team skills. Backend stays the same.

Should I use Firebase instead of a custom backend?

Firebase is faster to launch (auth, DB, push, storage bundled) but vendor-locked and costly past ~10K MAU. Custom on DomainIndia gives you full control and predictable costs.

Build your mobile API with predictable costs and full control. See our VPS plans

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app
Mobile App Backends on DomainIndia — JWT, Push Notifications, File Uploads