Mobile API Best Practices · Mobile Auth, Security & Flaky Networks

Media Uploads & Delivery

Direct-to-storage uploads, resumable transfers and image CDNs.

Don't stream large uploads through your API servers. Issue pre-signed URLs (S3/GCS/Azure) or use a resumable protocol (tus, GCS resumable, S3 multipart) so uploads survive network changes. Validate after upload (size, type sniffing, malware scan), then mark the media ready via a callback or event. For delivery, use an image CDN that resizes and converts (AVIF/WebP) per device, with long cache TTLs and content-hashed URLs.

Upload strategies

Criterion Through API server Pre-signed single PUT Resumable / multipart
Server load High None None
Survives network drop No No (restart) Yes (resume)
Large files (100MB+) Poor OK on good networks Best
Validation Inline After upload (event) After upload (event)
Complexity Low Low Medium
@router.post("/v1/uploads")
async def create_upload(body: UploadIn, user=Depends(current_user)):
    if body.size > 50 * 1024 * 1024 or body.content_type not in ALLOWED:
        raise ProblemError(422, "invalid-upload")
    key = f"uploads/{user.id}/{uuid7()}"
    url = s3.generate_presigned_url("put_object", ExpiresIn=900,
            Params={"Bucket": BUCKET, "Key": key, "ContentType": body.content_type})
    await media.create(key=key, owner=user.id, status="pending")
    return {"upload_url": url, "media_id": key}

Common pitfalls

  • Trusting client-declared content type without server-side checks.
  • Serving originals to every device.
  • Upload URLs that never expire.

Key points

  • Direct-to-storage, short-lived URLs
  • Resumable for large files
  • Image CDN for per-device variants

Further reading: tus resumable upload protocol

Practice questions

Why use pre-signed URLs for mobile uploads?

Answer

Clients upload directly to object storage, so API servers aren't tied up streaming bytes, and access is scoped and time-limited.

When should you use a resumable upload protocol?

Answer

For large files or unreliable networks, so an interrupted upload resumes from the last received byte instead of restarting.

Open in the app to mark lessons complete, take notes and track your progress.