Work

Systems I designed and built.

Platform architecture, data pipelines, and LLM tooling — each with the problem, the design, and what it changed.

  1. 2026 · Designed and built the platform layer

    pline.ai platform architecture

    The platform layer of a web data API — gateway, auth, metering, billing and durable workers — so every request is authorised, priced and charged once.

    ~200k
    requests/day since launch
    1
    customer identity: the API key
    18 → 2
    DB round trips on the team page
    • Python
    • FastAPI
    • GraphQL
    • PostgreSQL
    • Go
    • Temporal
    • AWS API Gateway
    • Lambda
    • SQS
    • Kubernetes
    • Stripe
    Read the case study
  2. 2026 · Designed and configured the gateway and its authorizer

    Putting API Gateway in front of a scraping engine

    One public edge for a private engine — keys, plans, credit checks and clear refusals at API Gateway, so only paid-for work reaches the engine.

    Private
    engine reachable only through the gateway
    1 query
    key → team, plan and credit balance
    No cache
    on authorizer results, so balances apply at once
    • AWS API Gateway
    • AWS Lambda
    • Python
    • PostgreSQL
    • AWS NLB
    • Kubernetes
    • Temporal
    Read the case study
  3. 2026 · Designed and built

    Usage metering: from Flink to durable workers in Go

    How every pline.ai request becomes a priced usage record and a credit debit — and why the pipeline moved from a Flink job to long-running Temporal workflows.

    ~200k
    requests/day metered
    1 event
    per request, metadata only
    0
    credits for failed requests
    • Go
    • Temporal
    • AWS SQS
    • Python
    • GraphQL
    • PostgreSQL
    • Apache Flink
    Read the case study
  4. 2025 · Built the metering path across four services

    Proxy cost per crawl run, end to end

    Measuring the proxy bandwidth every crawl run uses — from a Node proxy, through a Flink job, to a priced cost per run in the dataset history.

    4
    layers: proxy, stream, stats, API
    3 s
    usage reports from open HTTPS tunnels
    10 s
    event-time aggregation windows
    • Node.js
    • Java
    • Apache Flink
    • AWS Kinesis
    • Python
    • gRPC
    • MySQL
    Read the case study
  5. 2024 · Led the rollout and owned the service

    Crawler scheduling: from a polling loop to Temporal

    Taking a Temporal pilot to every scheduled crawl, then owning the scheduler for three years — rollout, pod lifecycle, timezones and async.

    3
    staged task-queue cut-overs
    1 h → 5 min
    pod shutdown grace period
    ~190
    PRs merged as release owner
    • Python
    • Temporal
    • gRPC
    • Kubernetes
    • MySQL
    Read the case study
  6. 2026 · Designed and built the service; directed the LLM engine

    AI data transformations: generated code, sandboxed

    Turning a plain-English instruction into a validated, sandboxed Python transform — and an LLM path for the rest, with a cost ceiling and real spend.

    2
    safety layers before code touches data
    2
    paths: generated code or per-row LLM
    ≥ 90%
    test coverage gate in CI
    • Python
    • gRPC
    • OpenAI API
    • Temporal
    • Redis
    • MySQL
    • MongoDB
    Read the case study
  7. 2025 · Designed and built the service; largest policy contributor

    A central authorization service on Cerbos

    A central authorization service on Cerbos — one gRPC call that resolves who is asking and what they touch, then lets versioned policies decide.

    1
    RPC: IsAllowed
    13
    resource kinds behind it
    4
    roles, from viewer to admin
    • Python
    • gRPC
    • Cerbos
    • SQLAlchemy
    • MySQL
    • Docker
    Read the case study
  8. 2025 · Designed and built; owned it through two versions

    GDPR-compliant user deactivation with Temporal

    A Temporal workflow that removes a user safely and in line with GDPR erasure — checks first, hands over what they own, then anonymises and deletes their data.

    6
    systems touched per deactivation
    4
    ownership checks before any change
    1
    run per user at a time
    • Python
    • Temporal
    • gRPC
    • MySQL
    • Auth0
    • Kong
    • AWS SNS
    Read the case study
  9. 2024 · Created the service; co-led it with a teammate

    A data profile for every crawl run

    A service that profiles each crawl run's dataset in its own Kubernetes job, orchestrated by Temporal — with a size gate, reconciliation and per-page reports.

    1 job
    per profile, cleaned up after 2 h
    10M
    cell limit before profiling is skipped
    1
    report per data page
    • Python
    • Temporal
    • gRPC
    • Kubernetes
    • MySQL
    • AWS S3
    Read the case study
  10. 2025 · Built the security and connectivity work in the delivery service

    Delivering data into customer systems, securely

    Encrypting stored delivery credentials, delivering into customer S3 by assumed role, modern SSH keys, and adding destinations without touching existing ones.

    0
    credential columns left in plaintext
    2
    STS hops for customer-owned S3
    1 day
    to ship a new destination, with tests
    • Python
    • SQLAlchemy
    • MySQL
    • AWS STS
    • paramiko
    • OAuth 2.0
    • gRPC
    Read the case study
  11. 2025 · Built the archival schedule and the restore path

    Archiving crawl data, and bringing it back

    Moving finished runs out of MongoDB on a schedule set by how the run ended, and restoring them from Avro on S3 in tuned batches when someone needs them.

    30 → 7 days
    retention for failed runs
    30 min
    to archive a run with no data
    3
    services, two languages
    • Python
    • Temporal
    • Go
    • MongoDB
    • AWS S3
    • Avro
    • Apache Flink
    • gRPC
    Read the case study
  12. 2026 · Led the region work across the scheduler, data and pipelines

    Adding a second AWS region to a running platform

    Routing crawls, task queues and data to a second AWS region one report at a time — and replacing static AWS keys with role-based credentials along the way.

    2
    AWS regions, one control plane
    1 report
    first moved, by allow-list
    30 min
    before a stuck task is re-queued
    • Python
    • Go
    • Java
    • Apache Flink
    • Kubernetes
    • Temporal
    • AWS IAM
    • AWS S3
    Read the case study
  13. 2026 · Created both services

    Two small services: a dedup cache and an event router

    A per-run dedup cache that crawlers call for every record, and a serverless router that turns platform events into Temporal workflows exactly once.

    1 call
    to check-and-set a record
    0
    routing changes to add an event type
    1
    workflow start per event, despite redelivery
    • Python
    • gRPC
    • Redis
    • AWS Lambda
    • Amazon EventBridge
    • AWS SAM
    • Temporal
    • DynamoDB
    Read the case study