Data, Storage & Async
Paved Path
- Datastore: Firestore (Native mode)
- Files: Firebase Storage (GCS)
- Cache: none initially
- Search: Algolia (nearโrealโtime sync)
- Async jobs: Cloud Tasks
- Eventing: Pub/Sub
- Backups: Daily Firestore exports; 30โday retention
- PII governance: Lean (tag collections, leastโprivilege IAM, default encryption)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import algoliasearch from 'algoliasearch';
admin.initializeApp();
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_API_KEY!);
const index = client.initIndex('users');
export const onUserWrite = functions.firestore
.document('users/{id}')
.onWrite(async (change, context) => {
const id = context.params.id;
if (!change.after.exists) return index.deleteObject(id);
const data = change.after.data()!;
await index.saveObject({ objectID: id, ...data });
});
import { CloudTasksClient } from '@google-cloud/tasks';
const client = new CloudTasksClient();
export async function enqueue(url: string, payload: any) {
const [res] = await client.createTask({
parent: client.queuePath('proj', 'loc', 'queue'),
task: { httpRequest: { httpMethod: 'POST', url, body: Buffer.from(JSON.stringify(payload)).toString('base64') } }
});
return res.name;
}
LLM Notes
- When modeling Firestore, optimize for access patterns. Prefer flat collections with indexes over deep nesting.