# Sarthak Agrawal — full public corpus Canonical identity: https://sarthakagrawal.dev/#person Website: https://sarthakagrawal.dev --- Source page: https://sarthakagrawal.dev/ # Sarthak Agrawal AI Infrastructure & Product Engineer. I build dependable AI products, from infrastructure to interface. Sarthak Agrawal is an AI infrastructure and product engineer building dependable local tools, model systems, and research products. ## Current work - Software Engineer, VaultWealth (Feb 2025 — Present): Backend services and reliability infrastructure for a wealth-management platform — financial planning, durable workflows, and the systems they run on. - Software Engineer, Front.Page (Jan 2022 — Jan 2025): Backend and data infrastructure for a fast-growing fintech social product — real-time market data, personalized feeds, and the AI systems layered on top. ## Selected products - [CodeVetter](https://codevetter.com): Local-first desktop AI code review for agent-generated code. - [PostTrainLLM](https://posttrainllm.com): A Mac-local LLM factory, runtime, and WebGPU learning playground. - [HeyPace](https://heypace.app): An on-device Mac voice agent with screen-aware local context. - [High Signal](https://highsignal.app): An evidence-first daily brief for technology, markets, and infrastructure. - [SaaS Maker](https://sassmaker.com): The broader directory and operating layer for the full product fleet. ## Canonical identity - Person ID: https://sarthakagrawal.dev/#person - Image: https://avatars.githubusercontent.com/u/43884471?v=4 - Location: India - Linkedin: https://www.linkedin.com/in/sarthakagrawal927 - Github: https://github.com/sarthakagrawal927 - X: https://x.com/sarthakcodes - Hugging Face: https://huggingface.co/sarthakagrawal927 - Email: sarthakagrawal927@gmail.com --- Source page: https://sarthakagrawal.dev/about # About Sarthak Agrawal Sarthak Agrawal is an AI infrastructure and product engineer building dependable local tools, model systems, and research products. ## Experience ### Software Engineer — VaultWealth Feb 2025 — Present. Backend services and reliability infrastructure for a wealth-management platform — financial planning, durable workflows, and the systems they run on. - Built a Financial Planning Service in Go and MySQL, including proprietary logic to compute clients’ financial health scores. - Migrated critical workflows to Temporal, eliminating 90% of unexpected failures and freeing roughly 3 engineering hours every day. - Led the web app’s migration from MUI to Tailwind and built responsive React components. ### Software Engineer — Front.Page Jan 2022 — Jan 2025. Backend and data infrastructure for a fast-growing fintech social product — real-time market data, personalized feeds, and the AI systems layered on top. - Built a real-time stock-data pipeline with Go, Kafka and Protocol Buffers — supporting DAU growth from 15k to 200k in 14 weeks. - Shipped vector-powered personalized feeds using BERT embeddings, GPT and Milvus, lifting home-feed engagement by 40%. - Built RAG chatbots on OpenAI APIs; the moderation bot cut human intervention in support queries by 90%. - Optimized hot paths with Redis — O(1) unread-news counts, 92% fewer session-refresh DB calls, and HTML build+load cut from 600ms to 60ms. - Integrated the Razorpay payment gateway, opening a new revenue stream and lifting overall revenue by 50%. - Designed real-time stock ticks over Socket.io with room-based, in-memory and Redis pub/sub subscription modes. ## Technical focus ### Backend & APIs Getting the service right comes before getting it fast. I care about clean contracts and knowing how things break before they do. Tools: Go, Node.js / TypeScript, Python, Protocol Buffers, REST APIs, Microservices ### Distributed Systems & Reliability Streaming pipelines, durable workflows, real-time delivery — the parts that decide whether a product survives getting popular. Tools: Apache Kafka, Temporal, Socket.io, Queue-based batching, Docker & Kubernetes, Prometheus ### AI / LLM Infrastructure Personalized feeds, retrieval pipelines, agents. The goal is AI that holds up in production, not just in a demo. Tools: RAG pipelines, OpenAI APIs, BERT embeddings, Milvus vector DB, GPT-powered features, Real-time vector enrichment ### Data & Storage Pick storage for how the data actually gets read and written. Then cache the slow paths until they stop being slow. Tools: MySQL, PostgreSQL, Redis, ClickHouse, Elasticsearch, BigQuery ## Education B.Tech, Computer Science Engineering, Manipal Institute of Technology (Aug 2018 — Jul 2022). --- Source page: https://sarthakagrawal.dev/projects # Projects The selected products below are the primary public work. SaaS Maker is the canonical directory for the broader maintained fleet. ## CodeVetter Local-first desktop AI code review for agent-generated code. - Product: https://codevetter.com - Source: https://github.com/Codevetter/codevetter - Organization: https://github.com/Codevetter ## PostTrainLLM A Mac-local LLM factory, runtime, and WebGPU learning playground. - Product: https://posttrainllm.com - Source: https://github.com/PostTrainLLM/posttrainllm - Organization: https://github.com/PostTrainLLM ## HeyPace An on-device Mac voice agent with screen-aware local context. - Product: https://heypace.app - Source: https://github.com/HeyPace/pace - Organization: https://github.com/HeyPace ## High Signal An evidence-first daily brief for technology, markets, and infrastructure. - Product: https://highsignal.app - Source: https://github.com/High-Signal-App/high-signal - Organization: https://github.com/High-Signal-App ## SaaS Maker The broader directory and operating layer for the full product fleet. - Product: https://sassmaker.com - Source: https://github.com/sass-maker/saas-maker - Organization: https://github.com/sass-maker --- Source page: https://sarthakagrawal.dev/resume # Sarthak Agrawal — AI Infrastructure & Product Engineer Location: India Email: sarthakagrawal927@gmail.com LinkedIn: https://www.linkedin.com/in/sarthakagrawal927 GitHub: https://github.com/sarthakagrawal927 ## Experience ### Software Engineer — VaultWealth Feb 2025 — Present · Peak XV - Created a Financial Planning Service (Go, MySQL) and wrote proprietary logic to calculate clients’ financial health score. - Migrated multiple workflows to Temporal, eliminating 90% of unexpected failures and freeing engineering ~3 hrs/day. - Transitioned the web app from MUI to Tailwind; built multiple responsive frontend components in React. ### Software Engineer — Front.Page Jan 2022 — Jan 2025 · YC S’21 - Developed a real-time pipeline for stock data using Go, Kafka and Protocol Buffers — helped DAU grow from 15k to 200k in 14 weeks. - Integrated vector-powered personalized feeds using BERT embeddings, GPT calls and Milvus as the vector DB — 40% more engagement on the home feed. Built a pipeline with real-time events from BigQuery for richer user vectors. - Built multiple (support, learning, assistant) RAG-based chatbots using OpenAI APIs; the moderation bot reduced human intervention in support queries by 90%. - Wrote a microservice in Node.js with MySQL (Prisma) for complete stock-fundamental data lifecycle management. - Built hot news with read/unread and last-visit tracking — tripled average news scroll count in 3 weeks. Used ClickHouse as the data aggregator with RudderStack as the pipeline. - Implemented O(1) space/time retrieval of a user’s unread news and global notification counts using Redis. - Integrated the Razorpay payment gateway with Node.js — a new revenue source and a 50% increase in overall revenue. - Implemented queue-based batching to improve database efficiency; optimized session handling with granular controls, reducing session-refresh DB calls by 92%. - Improved SEO performance by cutting HTML build and load time from 600ms to 60ms via Redis caching. - Incorporated FCM topic-based notifications, reducing delivery time by 90% and increasing delivery rate by 30%. - Planned and integrated real-time stock ticks via Socket.io with three modes: room-based, in-memory, or Redis for subscription management. ## Skills - **Languages:** JavaScript / TypeScript, Golang, Python - **Databases & Data Tools:** MySQL, PostgreSQL, Redis, Elasticsearch, Kafka, ClickHouse, Milvus, BigQuery - **Cloud & DevOps:** AWS, GCP, Docker, Kubernetes, Prometheus, Temporal, GenAI ## Selected projects ### Stumble — Social App Stack: Node.js, PostgreSQL (PostGIS), Redis, Docker, AWS, Flutter, Astro, Python - Launched a platform to help users connect with people nearby, encouraging meaningful in-person interactions. - Supported real-time chat, location-based profile filtering, face recognition, Google auth and push notifications. ### SignificantHobbies — Life Management App Stack: Next.js, Golang, PostgreSQL, Docker, AWS, Tailwind - Launched a personal productivity app to manage tasks, habits, food logs, journals and schedules. - Designed custom form validation, preference-based schedule generation and efficient CRUD operations. ### PlayWordle — CLI Puzzle Solver Stack: Golang - Devised a CLI application to solve New York Times Wordle puzzles with over a 97% success rate. ## Education B.Tech in Computer Science Engineering, Manipal Institute of Technology (Aug 2018 — Jul 2022). Coursework: Algorithms, Data Structures, DBMS, OOP, Operating Systems, Computer Networks. Built several internal college portals (recommendations, placement, fest, library management). --- Source page: https://sarthakagrawal.dev/blog # Writing by Sarthak Agrawal Technical notes about AI infrastructure, distributed systems, product engineering, and operating a public software fleet. - [How I run 23 products on Cloudflare without Argo](https://sarthakagrawal.dev/blog/fleet-performance-without-argo): A personal fleet on Workers and Pages had fast *.workers.dev URLs and slow custom domains. Here is the perf push that closed desktop LCP p75 under 500 ms — measured with distributional Lighthouse runs, not a single PageSpeed score. --- Source page: https://sarthakagrawal.dev/blog/fleet-performance-without-argo # How I run 23 products on Cloudflare without Argo A personal fleet on Workers and Pages had fast *.workers.dev URLs and slow custom domains. Here is the perf push that closed desktop LCP p75 under 500 ms — measured with distributional Lighthouse runs, not a single PageSpeed score. I ship a lot of small products — 23 live sites on Cloudflare Workers and Pages, mostly solo. The fleet had a split personality: `*.workers.dev` and `*.pages.dev` URLs were fast, but custom domains sat on a **400–1000 ms TTFB floor**. PageSpeed Insights gave me one number per URL. That number lied often enough that I built [psi-swarm](https://github.com/sass-maker/psi-swarm) to run Lighthouse many times and report **p50/p75/p90/p99** instead. This post is the narrative version. The structured case study with baseline, tactics, and results lives on [Foundry](https://sassmaker.com/case-study/fleet-performance). ## The constraint No Argo Smart Routing. No Vercel migration. Goal: **desktop LCP p75 under 500 ms** across the inventory. That sounds like a CDN problem until you look at the breakdown. On several Worker homepages, TTFB on a custom domain was 2–3× the same route on `*.workers.dev`. Cloudflare's free tier routing is real; fighting it with more JavaScript is not. ## What actually moved LCP **1. Astro static overlays for marketing `/` routes** Several apps are Next.js or React on Workers. The app shell is fine for logged-in flows; the landing page does not need SSR on every request. I added thin Astro sites that serve static HTML at `/` and link into the app. Same product behind the URL, but the LCP element is plain HTML at the edge — not a hydration waterfall. **2. Self-hosted fonts** Google Fonts CSS is render-blocking and adds DNS + connection setup. Moving to `@fontsource` (self-hosted, subsetted) removed a recurring 200–400 ms delay on mobile-slow presets. **3. Killed opacity-0 hero animations** This one hurt to admit. Framer Motion fade-ins on above-the-fold heroes were **40–70% of LCP render delay** on multiple sites. The hero image loaded; the browser waited to paint it because opacity was zero until JS ran. Removing or deferring those animations was often a bigger win than image compression. **4. Edge cache for semi-dynamic Worker homepages** For routes that cannot go fully static, `Cache-Control` headers plus `caches.default` in a thin worker wrapper let repeat visitors hit cached HTML. Not a substitute for static where static fits — but it trimmed TTFB on homepages that still need a Worker. **5. Distributional measurement** Single Lighthouse runs are noisy. psi-swarm runs the same URL across realistic device/network presets, stores history in SQLite, and surfaces regressions in a `/projects` dashboard. I stopped optimizing for one green PSI score and started watching **p75 LCP** week over week. ## Results Five sites closed under 500 ms desktop LCP p75 in the first push. The remaining gap is app-level TTFB on custom domains — a known Workers floor without paid routing. The wins were front-end and architecture choices I could ship in a week, not magic CDN settings. ## Try the tooling - **[psi-swarm](https://github.com/sass-maker/psi-swarm)** — CLI + local UI; runs stay on your machine - **[Fleet performance case study](https://sassmaker.com/case-study/fleet-performance)** — condensed write-up on Foundry - **[Fleet products hub](https://sarthakagrawal.dev/projects)** — all seven owned domains in one place If you are running a personal product fleet on Cloudflare, the highest-leverage move is usually: **static HTML at `/`, measure p75 not p50, and delete the hero fade-in.** Everything else is incremental. --- Source page: https://sarthakagrawal.dev/privacy # Privacy This is a static portfolio site. It has no account system, application database, advertising tracker, or user-content upload. The site may fetch public GitHub repository metadata at build time. Visiting linked products or external profiles is governed by those destinations. Contact: sarthakagrawal927@gmail.com --- Source page: https://sarthakagrawal.dev/work/posttrainllm # PostTrainLLM — a transformer built end to end A small GPT (~0.8M params, byte-level) written from scratch in three layers — a PyTorch reference, a hand-derived C++/WASM implementation, and a full WebGPU training loop — running entirely in a browser tab. Every layer's backward pass was finite-difference checked before being trusted. Role: Personal · Learning by building Year: 2026 Stack: PyTorch, C++, WebAssembly, WebGPU / WGSL, TypeScript, Emscripten Source: https://github.com/PostTrainLLM/posttrainllm Demo: https://posttrainllm.com ## The problem Most people who use transformers can describe attention with a diagram but couldn't write its backward pass from memory. I was one of them. Calling an LLM API doesn't teach you how it works; even idiomatic PyTorch mostly teaches you *its API*, not the underlying maths. So I set the bar: a working transformer, trainable from scratch in a browser tab, with **no autograd anywhere in the WASM and WebGPU paths**. Every layer something I'd written, derived, and tested. ## Architecture The same model exists at three levels, in build order: - **`python_ref/`** — a PyTorch reference: model, training loop, sampler, LoRA, evaluation. ~200 lines of clear code; the source of truth everything else is compared against. - **`wasm/`** — the same model in C++, with every backward pass *derived and written by hand*. There is no autograd. Compiled to WebAssembly with Emscripten; built twice — scalar and `-msimd128` for SIMD autovectorization. - **`webgpu/`** — full forward, backward, and AdamW on the GPU in WGSL. Tensors stay resident in GPU buffers between ops; a buffer pool reuses them across steps; an entire training step records into one command submission. A browser app picks a backend (WASM or WebGPU), trains in a Web Worker so the page never freezes, samples from the model, and checkpoints to OPFS so a run survives a refresh. ## Engineering decisions The principle throughout: **every layer had to be testable before it was trusted.** Each kernel has a finite-difference gradient check against a reference implementation; each model has an "overfit gate" — train on a single batch, the cross-entropy loss must collapse to near-zero or the build doesn't ship. That one property is what made writing a hand-derived WebGPU backward pass tractable. Bugs were caught at the layer they lived in, not three layers later as a mystery in the loss curve. The three implementations were built in that order on purpose: the PyTorch reference exists so the C++ has something to be wrong against; the C++ overfit gate exists so the WebGPU does too. Each level pins the next. The WebGPU training port itself went in as six staged pull requests — GPU tensors and matmul, the elementwise ops, attention, embeddings + cross-entropy + AdamW, the orchestrator, the app integration — each parity-checked against WASM before the next began. When everything is verifiable, the diffs stay small and the bugs stay local. One note on honesty. An earlier write-up of mine documented WebGPU training as ~2× slower than WASM based on automated measurements; I later discovered the headless CI was using `swiftshader`, a **software** WebGPU adapter, so the comparison was software-WebGPU racing SIMD-WASM — not a valid GPU number. The doc was corrected, the claim withdrawn, and the real-hardware speed left explicitly unmeasured. The project's whole method was "verify before claiming"; that was a miss against it, fixed in the open. ## Outcome A complete transformer that runs in a browser tab — ~0.8M params, byte-level, trains from scratch, generates samples, survives a refresh. The overfit gate sits at cross-entropy 5.55 → 0.002. The SIMD WASM build trains at ~1.6× the scalar speed. The WebGPU training loop is correct end to end (24/24 kernels parity-checked, the GPU overfit gate passes); the real-hardware speedup is for whoever opens the playground on a real GPU to read off — which is, honestly, the right way to state an unmeasured number. The model itself is too small to write coherent prose and is meant to be. The point of the project was the learning trail behind it kept visible — the write-ups, the staged PRs, every layer's test. That part worked. --- Source page: https://sarthakagrawal.dev/work/vector-feeds # Vector-Powered Personalized Feeds A home feed that actually learns what you like. Content gets embedded with BERT, ranked by similarity in Milvus, and the user vector keeps updating from live events. Engagement went up 40%. Role: Software Engineer · Front.Page Year: 2024 Stack: Go, Milvus, BERT, OpenAI / GPT, BigQuery ## The problem Front.Page's home feed showed everyone roughly the same thing. For a fintech social product that is a real cost: the user who follows small-cap biotech and the user who only watches index funds have nothing in common, but the feed treated them identically. Personalization is easy to describe and hard to ship: it needs a representation of *content*, a representation of *each user*, a fast way to match them, and — the part most attempts skip — a way to stay current as behaviour changes. ## Architecture The feed is a vector-matching system with four moving parts: - **Content embeddings** — posts and news are embedded with BERT into a shared vector space, so "similarity" becomes a geometric question instead of a keyword one. - **Vector search** — embeddings live in **Milvus**, which serves approximate-nearest-neighbour queries fast enough to rank a feed on request. - **User vectors** — each user is represented by a vector derived from what they actually engage with, not what they signed up claiming to like. - **Real-time enrichment** — a pipeline streams live behavioural events out of **BigQuery** and folds them back into the user vector, so the representation tracks the user instead of going stale. GPT calls handle the language-shaped parts of the pipeline where a model is genuinely the right tool, rather than being the whole design. ## Engineering decisions The decision that made this work was treating the **user vector as a living object**. A personalization system that embeds you once at signup is wrong within a week. Wiring real-time events from BigQuery back into the vector meant the feed adapted continuously — the same day a user's interests shifted, not the next sprint. Putting embeddings in a purpose-built vector database, rather than bolting similarity onto the primary store, kept ranking latency low enough to compute the feed at request time. ## Outcome Home-feed engagement rose **40%**. More importantly, the system improved on its own as users used it — the architecture, not a one-off model, was the product. It is the clearest example of what I mean by *AI infrastructure*: the model is a component; the pipeline around it is the engineering. --- Source page: https://sarthakagrawal.dev/work/realtime-pipeline # Real-Time Market Data Pipeline The streaming backbone of a fintech social app. Go services push live market data through Kafka to clients in real time — and it held up while daily users went from 15k to 200k. Role: Software Engineer · Front.Page Year: 2023 Stack: Go, Kafka, Protocol Buffers, Socket.io, Redis ## The problem Market data is unforgiving infrastructure: it arrives continuously, it is only valuable while it is fresh, and the number of clients waiting for it was growing fast. Over fourteen weeks daily actives went from 15k to 200k — a **13×** jump — and the data path had to absorb that without the user ever seeing stale prices. The hard part is not ingesting the data. It is fanning it out to a moving target of connected clients, cheaply enough that scale does not become a cost crisis. ## Architecture The pipeline separates ingest from delivery so each side can scale on its own: - **Go services** — ingest and processing run as Go services, chosen for cheap concurrency and predictable latency under load. - **Kafka** — sits between ingest and fan-out as a buffer and decoupling layer, so a burst on one side never stalls the other. - **Protocol Buffers** — the wire format throughout. Compact and fast to encode/decode, which matters enormously when the same tick is serialised for thousands of subscribers. - **Socket.io delivery** — real-time stock ticks reach clients over Socket.io, with three selectable subscription modes: **room-based** fan-out, an **in-memory** path, and **Redis pub/sub** for distributed subscription state. ## Engineering decisions Offering three subscription modes was deliberate. Different workloads have different right answers — in-memory is fastest until you need more than one node; Redis pub/sub coordinates across many. Making it a choice meant the system fit the deployment instead of forcing one trade-off everywhere. Scaling to 200k DAU also meant attacking the database. Queue-based batching cut write load; granular session handling reduced session-refresh DB calls by **92%**; and caching page renders in Redis took HTML build + load from **600ms to 60ms** — a 10× win that compounded across every request. ## Outcome A real-time data path that grew 13× in three months without a rewrite — and stayed fast while doing it. The lesson I keep: at scale, the wins are rarely one clever thing. They are a dozen unglamorous decisions — batch this, cache that, decouple here — each removing a little load. --- Source page: https://sarthakagrawal.dev/work/rag-agents # RAG Agents for Support & Learning A set of RAG chatbots — support, learning, assistant — built on OpenAI APIs and grounded in real product docs. The support one cut human replies by 90%. Role: Software Engineer · Front.Page Year: 2024 Stack: Node.js, OpenAI APIs, RAG, Vector retrieval ## The problem A raw LLM is confidently wrong about your product. It has never seen your docs, your edge cases, or last week's feature — so a support bot built on prompting alone either hallucinates or hedges, and both erode trust. The goal was a set of assistants that were genuinely *useful*: a support agent, a learning agent and a general assistant, each answering from what was actually true about the product rather than what the model guessed. ## Architecture Every agent follows the same retrieval-augmented shape: - **Knowledge retrieval** — the relevant product knowledge for a question is retrieved first, so the model answers *from* sources instead of from memory. - **Grounded generation** — OpenAI APIs generate the response over retrieved context, which keeps answers specific and current and makes them auditable. - **Three surfaces, one core** — support, learning and assistant agents share the same retrieval-and-generation core, differing in their knowledge scope and tone rather than being three separate builds. - **A moderation agent** — a dedicated agent triages incoming support queries, resolving the routine ones and escalating only what genuinely needs a human. ## Engineering decisions The principle throughout: **retrieval is not optional.** Grounding every answer in retrieved knowledge is what separates an assistant people rely on from a demo that embarrasses you in week two. It also made the system improvable — better answers came from better knowledge, not from prompt-wrangling. Framing the moderation bot as a triage layer, not a replacement, was the other key call. It handled the bulk of routine load and *escalated* the rest, so the failure mode was "a human looks at it", never "a user gets a wrong answer with confidence". ## Outcome Human intervention in support queries dropped **90%**. The team spent its time on the hard, genuinely novel tickets while the routine majority resolved themselves — and because every answer was retrieval-backed, the bots got better simply by keeping the knowledge base current. --- Source page: https://sarthakagrawal.dev/work/durable-workflows # Durable Financial Workflows Financial planning can't run on workflows that quietly break. Moving them to Temporal killed 90% of the random failures and gave the team back about three hours a day. Role: Software Engineer · VaultWealth Year: 2025 Stack: Go, Temporal, MySQL ## The problem In wealth management, a workflow that fails halfway is worse than one that never ran. A multi-step financial planning process — pulling data, running calculations, writing results — that dies in the middle leaves the system in a state nobody designed. The old workflows failed in exactly those ways: unexpectedly, partially, and often enough that engineers were spending hours every day diagnosing and manually replaying them. That is not a bug backlog — it is a missing infrastructure layer. ## Architecture The fix was to stop treating durability as something each workflow re-invents: - **Temporal** — workflows were migrated onto Temporal, which makes execution *durable*: progress is persisted step by step, so a crash or restart resumes from where it stopped instead of starting over or stalling. - **Go workflow logic** — the planning logic itself runs as Go, with the unreliable parts (network calls, external dependencies) expressed as Temporal activities that retry on well-defined policies. - **Financial Planning Service** — alongside the migration, the planning service itself was built in Go and MySQL, including the proprietary logic that computes each client's financial health score. ## Engineering decisions The core decision was to make **reliability a property of the platform, not of each developer's diligence.** Asking every workflow to handle its own retries, idempotency and partial-failure recovery guarantees inconsistency. Temporal moves those guarantees underneath the business logic, where they are uniform and hard to get wrong. The payoff is also operational: a durable workflow that hits a transient error recovers itself. There is simply less for a human to be paged about. ## Outcome Unexpected failures dropped **90%**, and the engineering time previously lost to diagnosing and replaying broken runs — about **three hours a day** — went back into building. The financial workflows stopped being a thing the team worried about and became a thing the team trusted.