Notes

Short engineering notes and code snippets from building production AI systems on Firebase and Google Cloud. Each one is a gotcha I hit and the fix that held. 7 notes, newest first.

DateNoteTag
A Stale File in public/ Silently Shadows Its Dynamic Astro Route

Astro serves public/ before src/pages/, and a same-named static file wins with no warning at build time. My generated robots.txt and podcast feed had never once been served.

verifyNoShadowedRoutes.mjs
import { readdirSync, existsSync } from "node:fs";
import { join, relative } from "node:path";

// A route is shadowed when public/<path> and a src/pages/<path>.{js,ts,mjs,astro}
// generator both exist, at any depth. public/ wins, so the generator is dead code.
export function findShadowedRoutes(publicDir = "public", pagesDir = "src/pages") {
  const shadowed = [];
  for (const entry of readdirSync(publicDir, { recursive: true, withFileTypes: true })) {
    if (!entry.isFile()) continue;
    const served = join(entry.parentPath, entry.name);
    const generator = [".js", ".ts", ".mjs", ".astro"]
      .map((ext) => join(pagesDir, relative(publicDir, served) + ext))
      .find((candidate) => existsSync(candidate));
    if (generator) shadowed.push({ served, dead: generator });
  }
  return shadowed;
}

const hits = findShadowedRoutes();
if (hits.length > 0) {
  for (const hit of hits) {
    console.error(`${hit.served} shadows ${hit.dead}. The generator never runs.`);
  }
  process.exit(1);
}
Astro, Static Assets, SEO
A Naive Quoted-String Regex Truncates at the First Escaped Quote

My subtitle parser used [^"]+ and stopped dead at the first escaped inner quote. One social card shipped for weeks with a six-character subtitle reading "From \".

parseQuoted.mjs
// Wrong: [^"]+ halts at the backslash-escaped quote inside the value.
const NAIVE = /subtitle:\s*"([^"]+)"/;

// Right: consume either a non-quote non-backslash character, or any
// backslash-escaped pair, so escaped quotes stay inside the capture.
const ESCAPE_AWARE = /subtitle:\s*"((?:[^"\\]|\\.)*)"/;

// \uXXXX becomes its character, \n \r \t their controls, and any other
// escaped character (\" \' \\) stands for itself.
const CONTROLS = { n: "\n", r: "\r", t: "\t" };
export const unescape = (value) =>
  value.replace(/\\(u[0-9a-fA-F]{4}|.)/g, (_, esc) =>
    esc.length === 5 ? String.fromCharCode(parseInt(esc.slice(1), 16)) : CONTROLS[esc] ?? esc);

export function parseSubtitle(source) {
  const match = source.match(ESCAPE_AWARE);
  return match ? unescape(match[1]) : null;
}
Regex, Build Tooling, Node.js
A Retried Agent Tool Call Runs Twice Without an Idempotency Key

When autonomous agents execute external tool calls (such as payment triggers or cloud resource provisioning), network blips or TCP disconnects frequently cause the agent client to retry the request.

idempotencyMutex.ts
// Claim the key with create(), then run the tool outside any transaction
import { Firestore, Timestamp } from "firebase-admin/firestore";

const ALREADY_EXISTS = 6; // gRPC status create() fails with when the document exists
const CLAIM_TTL_MS = 24 * 60 * 60 * 1000;

export async function withIdempotency<T>(
  db: Firestore, key: string, executeTool: (key: string) => Promise<T>,
): Promise<T> {
  const ref = db.collection("idempotency_keys").doc(key);
  try {
    // expireAt is a Timestamp so a TTL policy on it can delete abandoned claims
    await ref.create({ status: "in_flight", expireAt: Timestamp.fromMillis(Date.now() + CLAIM_TTL_MS) });
  } catch (err) {
    if ((err as { code?: number }).code !== ALREADY_EXISTS) throw err;
    const doc = (await ref.get()).data();
    if (doc?.status === "completed") return doc.cachedResult as T;
    throw Object.assign(new Error(`tool call ${key} is still in flight, retry later`), { status: 409 });
  }
  // Pass the key on so the downstream API can dedupe too; a failed call releases the claim
  const result = await executeTool(key).catch(async (err: unknown) => {
    await ref.delete();
    throw err;
  });
  await ref.update({ status: "completed", cachedResult: result });
  return result;
}
Firestore, AI Agents
A TCP Chunk Can Split One UTF-8 Character: Buffer the Bytes Before You Decode

LLM streaming endpoints emit UTF-8 text chunks over HTTP/2 or Server-Sent Events (SSE). Because TCP packet boundaries operate independently of UTF-8 character encoding, multi-byte sequences can tear cleanly across chunk boundaries.

streamDecoder.js
import { StringDecoder } from "node:string_decoder";

export async function* decodeSafeStream(rawByteStream) {
  const decoder = new StringDecoder("utf8");
  for await (const chunk of rawByteStream) {
    // StringDecoder preserves trailing partial UTF-8 bytes across iterations
    const safeText = decoder.write(chunk);
    if (safeText) yield safeText;
  }
  const finalChunk = decoder.end();
  if (finalChunk) yield finalChunk;
}
Streaming, Node.js
Cloud Run Can Verify Firebase App Check Tokens Without the Admin SDK

When deploying standalone containers on Cloud Run, you can verify incoming Firebase App Check JWTs inside Express/Fastify middleware by checking the token against Google's public JWKS.

appCheckMiddleware.ts
import type { FastifyReply, FastifyRequest } from "fastify";
import { createRemoteJWKSet, jwtVerify } from "jose";

const PROJECT_NUMBER = process.env.GCP_PROJECT_NUMBER;
if (!PROJECT_NUMBER) throw new Error("GCP_PROJECT_NUMBER is not set");
const JWKS = createRemoteJWKSet(new URL("https://firebaseappcheck.googleapis.com/v1/jwks"));

export async function verifyAppCheck(req: FastifyRequest, reply: FastifyReply) {
  const token = req.headers["x-firebase-appcheck"];
  if (typeof token !== "string") {
    return reply.status(401).send({ error: "Missing App Check token." });
  }
  try {
    await jwtVerify(token, JWKS, {
      algorithms: ["RS256"],
      typ: "JWT",
      issuer: `https://firebaseappcheck.googleapis.com/${PROJECT_NUMBER}`,
      audience: `projects/${PROJECT_NUMBER}`,
    });
  } catch {
    return reply.status(401).send({ error: "Invalid App Check verification." });
  }
}
Cloud Run, App Check
Count Agent Tokens With FieldValue.increment Instead of a Transaction

When an agent fires tool calls in parallel, a read-then-write transaction on one usage document retries under contention. FieldValue.increment adds each call's tokens in a single write, so no count is lost.

tokenCounter.ts
import { FieldValue, type Firestore } from "firebase-admin/firestore";

export async function recordTokenUsage(
  db: Firestore, userId: string, promptTokens: number, completionTokens: number,
): Promise<void> {
  const ref = db.collection("token_usage").doc(userId);
  await ref.set(
    {
      promptTokens: FieldValue.increment(promptTokens),
      completionTokens: FieldValue.increment(completionTokens),
      totalInvocations: FieldValue.increment(1),
      lastUpdated: FieldValue.serverTimestamp(),
    },
    { merge: true }
  );
}
Firestore, Tokenomics
When the Spend Cap Trips, Return a 402 So the Agent Can Checkpoint

When a Firebase spend cap trips, your client-side app will start throwing errors for that service. If your agent does not catch them explicitly, it can crash mid-execution and leave database state partially mutated.

circuitBreaker.ts
// status is the HTTP status on the SDK's error, such as ApiError.status in @google/genai
export class CheckpointRequired extends Error {
  readonly statusCode = 402; // Payment Required: the agent saves its progress and stops
}

const RETRIES = 4;
let breakerOpen = false; // stays open until resetBreaker() runs after the cap is lifted
export const resetBreaker = () => { breakerOpen = false; };

export async function callWithSpendCapGuard<T>(apiCall: () => Promise<T>): Promise<T> {
  if (breakerOpen) throw new CheckpointRequired("Breaker open: model calls are paused. Checkpoint and stop.");
  for (let attempt = 0; ; attempt++) {
    try {
      return await apiCall();
    } catch (err) {
      const status = (err as { status?: number }).status ?? 0;
      if (status !== 402 && status !== 429 && status < 500) throw err; // the request itself is wrong
      if (status === 402 || attempt === RETRIES) {
        breakerOpen = true;
        throw new CheckpointRequired(`Still failing with ${status} after ${attempt} retries. Checkpoint and stop.`);
      }
      await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** attempt)); // 429s are usually transient
    }
  }
}
Cloud Billing, Gemini API, Tokenomics