Skip to content

$ whoami

Math taught me to see problems as puzzles. Code taught me to solve them. Now, I’m teaching an AI to join in.

How I think

Three decisions, and the reasoning behind each one.

Optimization under high traffic

A media platform's article pages went from a few hundred to tens of thousands of concurrent readers within minutes of a story going viral — and every one of them was hitting the same API endpoint at once.

When traffic spikes, the worst decision is letting every user fire their own call to the backend. Here's how I design the caching layer so it can absorb the spike without falling over.

Decision: Stale-while-revalidate caching for API calls, combined with deduplication of concurrent requests, so a traffic spike produces one backend call instead of thousands of identical ones.

TypeScriptReactCachingPerformance
useCachedFetch.ts
type CacheEntry<T> = {
  data: T;
  fetchedAt: number;
  inFlight: Promise<T> | null;
};

const cache = new Map<string, CacheEntry<unknown>>();

// Serve cached data instantly; only go back to the network once it's this old.
const STALE_AFTER_MS = 30_000;

export function useCachedFetch<T>(key: string, fetcher: () => Promise<T>) {
  const [data, setData] = useState<T | null>(
    () => (cache.get(key)?.data as T | undefined) ?? null
  );

  useEffect(() => {
    const entry = cache.get(key) as CacheEntry<T> | undefined;
    const isStale = !entry || Date.now() - entry.fetchedAt > STALE_AFTER_MS;

    // Fresh cache hit: the UI already has the data, nothing to do.
    if (!isStale) return;

    // Dedupe: if a request for this key is already in flight — say, from
    // another component mounted a millisecond earlier during the same
    // spike — piggyback on it instead of firing a second identical call.
    const request =
      entry?.inFlight ??
      fetcher().then((result) => {
        cache.set(key, { data: result, fetchedAt: Date.now(), inFlight: null });
        return result;
      });

    cache.set(key, {
      data: entry?.data as T,
      fetchedAt: entry?.fetchedAt ?? 0,
      inFlight: request,
    });

    // Trade-off: on failure we keep serving the last good (stale) value
    // instead of surfacing an error — resilience over freshness.
    request.then(setData).catch(() => {});
  }, [key, fetcher]);

  return data;
}

Multi-repo / DevOps

A small engineering team was shipping to both a QA and a production environment, with deploys handled by hand — meaning the only thing standing between a broken branch and production was whoever remembered to run the checks that day.

This isn't feature code — it's process design. The job here wasn't writing a clever function, it was making sure the whole team could ship without anyone having to remember to be careful.

Decision: A CI/CD pipeline with quality gates (lint, test, build) that every branch must clear, where QA deploys automatically off develop and production only ships from main behind a required-reviewer environment.

CI/CDGitHub ActionsDevOpsNode.jsPM2
.github/workflows/deploy.yml
name: CI/CD

on:
  push:
    branches: [main, develop]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  test:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test -- --coverage

  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/

  deploy-qa:
    # develop merges go straight to QA. This environment exists to break —
    # the gate is "did it build," not "did a human sign off."
    if: github.ref == 'refs/heads/develop'
    needs: build
    runs-on: ubuntu-latest
    environment: qa
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build-output
      - run: ./scripts/deploy.sh qa # pm2 reload on the QA host

  deploy-production:
    # Production only ships from main, and only behind a required reviewer
    # on the "production" GitHub environment — one bad merge shouldn't be
    # able to reach real users without a second set of eyes.
    if: github.ref == 'refs/heads/main'
    needs: build
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build-output
      - run: ./scripts/deploy.sh production # pm2 reload on the prod host

Local AI agent with Ollama

A personal project: a local agent that runs entirely on-device against Ollama, and needs to act on the real world — check the weather, do a conversion, look something up — without ever giving the model direct access to the filesystem, network, or shell.

The model doesn't get to run anything. It gets to ask. This is the pattern that draws that line — and it's also the base for the playground below, simplified to run entirely in your browser.

Decision: Tool-calling orchestration: the model is given a fixed catalog of named tools, its response is parsed for a structured tool call, and only the orchestrator — never the model itself — executes it.

TypeScriptLLMOllamaTool calling
agent.ts
interface Tool {
  name: string;
  description: string;
  execute: (args: Record<string, unknown>) => string;
}

const tools: Tool[] = [
  {
    name: "get_weather",
    description: "Get the current weather for a city",
    execute: ({ city }) => `${city}: 22°C, clear skies`,
  },
  {
    name: "convert_currency",
    description: "Convert an amount from one currency to another",
    execute: ({ amount, from, to }) =>
      `${amount} ${from} ≈ ${(Number(amount) * 1.08).toFixed(2)} ${to}`,
  },
];

// The model never calls a function directly — it returns structured JSON
// naming a tool and its arguments. We parse that decision ourselves and
// decide whether to act on it, which is what keeps the model sandboxed.
interface ToolCall {
  tool: string;
  args: Record<string, unknown>;
}

function parseToolCall(modelOutput: string): ToolCall | null {
  try {
    const parsed = JSON.parse(modelOutput);
    if (typeof parsed.tool === "string") return parsed as ToolCall;
  } catch {
    // Not valid JSON — treat the output as a plain text reply instead.
  }
  return null;
}

export async function runAgentTurn(modelOutput: string): Promise<string> {
  const call = parseToolCall(modelOutput);

  // No tool call parsed: the model just answered in plain text.
  if (!call) return modelOutput;

  const tool = tools.find((t) => t.name === call.tool);
  if (!tool) return `Error: no tool named "${call.tool}"`;

  return tool.execute(call.args);
}

Try it yourself

The tool-calling pattern from the case study above, live.

Edit the code, change what the "model" replied with, and run it — everything executes right here in your browser, no server involved.

Loading playground…

Stack

toolkit.json

$ cat toolkit.json

// when I need iteration speed

ReactTypeScriptStyled Components

// when the project grows

Node.jsExpressNestJSMongoDB

Also in the toolkit

Shipped production code with these too — not my default reach, but ready if a project needs them.

Frontend

JavaScript · HTML · CSS · Sass/Less/Scss · jQuery · Angular · Redux · GraphQL

Backend, CMS & data

PHP · WordPress · Wagtail · Python · Java · SQL

Cloud & DevOps

Git · GitHub · GitLab · Bitbucket · AWS · GCP · PM2 · Keycloak

Tooling & testing

Webpack · npm · Jest · Enzyme · React Testing Library · SEO

Verified, not claimed

The performance and accessibility numbers behind this site.

This isn't a badge I made up — it's a real Lighthouse audit against a production build, and you can re-run it yourself any time.

lighthouse

$ lighthouse https://www.mauriciorodriguez.dev/en --preset=desktop,mobile

performancedesktop 100/100mobile 98/100
accessibilitydesktop 100/100mobile 100/100
best practicesdesktop 100/100mobile 100/100
seodesktop 100/100mobile 100/100

Measured 2026-08-06

Contact

The fastest way to reach me is email or LinkedIn.