Skip to content
Shirisha Gujja

Software Engineer · San Jose, CA

Shirisha Gujja

Building reliable backend systems and AI-powered products.

Currently pursuing an MS in Software Engineering at San José State University, after two years building LLM-powered enterprise features and ETL infrastructure at S&P Global. I work end to end, but the backend — and the systems underneath it — is where I spend most of my attention.

Experience

Where I've worked

Two roles at S&P Global, on either side of the line between raw enterprise data and the AI features built on top of it.

S&P Global

Software Development Engineer

Sep 2024 – Dec 2025

Hyderabad, India

Built the tool-calling layer connecting enterprise LLM features to internal GraphQL services, and the React surfaces that put the results in front of users.

  • Designed MCP-based tool interactions that let LLMs retrieve structured data from internal GraphQL services and drive context-aware application workflows, rather than treating the model as a bolt-on chat widget.
  • Naive tool calls pulled full GraphQL responses regardless of what the model needed next. Built selective retrieval mechanisms so tool calls fetch only the fields required, cutting unnecessary data transfer and making model-to-backend interactions faster and more reliable.
  • Built the React components and reusable widgets that surface AI-generated insights and backend data, so the output of the above pipeline is legible to actual users rather than raw model output.
  • Trained GitHub Copilot on historical support data to cut repetitive manual triage work on the team.
ReactGraphQLMCPLLM tool callingREST APIsGit

S&P Global

Software Development Engineer Intern

Jan 2024 – Jul 2024

Hyderabad, India

Took a daily data refresh job from 9 hours to 1 hour 27 minutes by re-architecting it off MS SQL Server stored procedures and onto Redshift-backed Python ETL.

  • A critical daily refresh job, implemented as MS SQL Server stored procedures, was taking 9 hours to run end to end. Led a proof-of-concept to re-architect it on Amazon Redshift with PostgreSQL-based stored procedures.
  • Engineered modular Python ETL scripts to orchestrate the new Redshift workflows, with explicit error handling, structured logging, retry logic, and automated data-validation checks rather than a bare happy-path script.
  • Reduced execution time from 9 hours to 1 hour 27 minutes — a 79% improvement — and presented the solution for adoption as the team's standard refresh process.
PythonAmazon RedshiftPostgreSQLMS SQL ServerAWS LambdaETL

Selected work

Two systems, built and documented phase by phase

Both went from a data model on paper to a deployed, containerized application — architecture decisions, trade-offs, and verification steps recorded as they were made, not written up after the fact.

Case study 01

FitForge

AI-powered fitness platform, built and deployed phase by phase

Live · 16/16 phases complete

Problem

Fitness tracking is usually split across single-purpose apps — a calorie counter, a workout log, a spreadsheet for weight over time — none of which share data. That means any "AI coaching" those apps offer is generic, because it isn't reasoning over a person's actual logged history across all three.

What I built

  • Built one data model spanning workouts, nutrition, and body progress, so the AI coach reasons over what a user actually logged instead of giving generic advice.
  • Architected six modular backend domains — auth, workouts, nutrition, progress, profile, and AI coaching — each with its own models, validation schemas, service layer, and REST routes, so new features never risked breaking ones already shipped.
  • Shipped a Next.js frontend that acts as its own backend-for-frontend: Route Handlers hold JWTs in httpOnly cookies, so the browser JavaScript never sees an access token.
  • Deployed the full stack to a real AWS EC2 instance behind nginx, with a genuine Let's Encrypt HTTPS certificate — not a local-only demo.

Architecture

/* /api/v1/*internal, never via nginxBrowsernginx:80 / :443Next.js BFFRoute Handlers · httpOnly cookiesFastAPI backendREST APIPostgreSQLasyncpgRedisCelery brokerCelery worker + beatOpenAIAI coach only

Engineering decisions

BFF pattern over client-held tokens

Next.js Route Handlers proxy every backend call and hold the JWT in an httpOnly cookie. It costs an extra request hop, but it closes off the class of XSS-reads-localStorage token theft that a client-held access token is exposed to.

Session security beyond a bare JWT

Refresh token rotation, password hashing, session revocation, and automatic silent token refresh — so a session survives normal use without ever asking a user to babysit expiring tokens.

The AI coach is designed to fail without taking the app down

OpenAI calls return a typed 503 on a missing key or exhausted quota and a 502 on other upstream errors, with structured response validation — a third-party outage degrades one feature, not the whole product.

Real infrastructure caught what unit tests didn't

Running the actual Docker Compose stack surfaced an nginx route-shadowing bug, a Compose port override that silently no-op'd, and a migration that raced its own auto-migrate-on-restart — none of which a unit test suite alone would have caught.

Production considerations

  • 16 phases, each independently validated end to end before the next began: 6 backend domains, then the matching frontend surface for each, then Docker/nginx, then CI, then production deploy config.
  • GitHub Actions CI runs lint, test, and build for both the FastAPI backend and the Next.js frontend on every change.
  • Live on AWS EC2 behind nginx path-based routing, with HTTPS issued via certbot's Let's Encrypt webroot method.
  • Background work — AI generation jobs and scheduled tasks — runs on Celery workers with Redis as the broker, kept off the request path.

Stack

FastAPISQLAlchemy 2.0 (async)AlembicCeleryRedisPostgreSQL 16Next.js (App Router)TypeScriptTailwind CSSDocker ComposenginxAWS EC2GitHub ActionsOpenAI API

Case study 02

Meridian

Event-driven personal finance platform with a transactional outbox

16/16 phases complete · infra validated, not deployed

Problem

Personal finance data is scattered across banks, brokerages, and manual tracking. Getting one accurate picture — spending by category, budget adherence, net worth, investment performance — usually means a spreadsheet, or handing a third party read access to every account.

What I built

  • Centralized accounts, transactions, budgets, goals, and investments behind authentication the user controls, with Plaid handling bank sync so data doesn't have to be entered by hand.
  • Every write that needs downstream processing (categorization, anomaly detection) commits an outbox row in the same database transaction as the write itself, so the event can never be lost even if the message broker is down at that instant.
  • Split categorization, anomaly detection, and notification fan-out into three independently deployable consumer services reading from Kafka (Redpanda), instead of doing that work inline on the request path.
  • Wired distributed tracing through every hop — including across Kafka, which has no built-in trace propagation the way HTTP middleware does — so one user action shows up as one connected trace, not four disconnected ones.

Architecture

HTTPS + WSsame transactionpub/subBrowserNext.js dashboardcore-apiFastAPI · REST + WSOutbox publisherpolls every 3sPostgreSQLsource of truthRediscache · idempotencyRedpandaKafka APIenrichment-serviceanomaly-servicenotification-servicemarket-data-servicescheduled pollerPlaid · OpenAI · market data

Engineering decisions

Transactional outbox, publish-then-mark by construction

A background publisher polls unpublished outbox rows and marks a row published only after Kafka confirms delivery — so a crash between the two never produces a false 'delivered' record. Async end-to-end with aiokafka rather than the sync confluent-kafka SDK, so the whole app stays non-blocking.

Idempotency enforced in the database, not just in application logic

Alert creation is backed by a real UNIQUE(source_event_id, alert_type) constraint, verified with a test that simulates message redelivery and asserts no duplicate alert is created — closing a correctness gap that's easy to claim and easy to get wrong.

Rotating refresh tokens with theft detection

A refresh token that's presented twice — already used, or already revoked — kills its entire token family, not just the one token, so a stolen-and-replayed token can't quietly ride alongside a legitimate session.

Grounded AI insights with a real fallback

The LLM only ever sees pre-computed spend aggregates, never raw transaction rows, and a deterministic template summary — computed from the same aggregates — keeps the feature available when the API call fails or isn't configured, rather than showing an error or a mocked number.

Chaos-tested against the real stack, not reasoned about in the abstract

Killing the enrichment service mid-pipeline loses no data, because Kafka consumer-group offsets resume exactly where it left off. Stopping the Kafka broker entirely doesn't touch the request path at all, since the outbox never makes a synchronous call to it.

Production considerations

  • Rebuilt from an earlier version across 16 reviewed phases, each with its own design doc and, for cross-cutting decisions, an ADR under docs/adr/.
  • Observability stack wired end to end: OpenTelemetry traces into Tempo, Prometheus metrics, structured JSON logs into Loki, with a working Grafana trace-to-logs correlation via a hand-carried trace_id.
  • Infrastructure as code for two environments (a Terraform + Helm/EKS design, and a single-EC2 path sized from real docker stats measurements) — written and validated in CI, deliberately never applied against real AWS, and documented as exactly that: a scope boundary, not an oversight.
  • CI runs backend, frontend, and three independent consumer services as separate jobs, plus a chaos-smoke-test job on main that actually kills and restarts containers against a full Compose stack.

Stack

FastAPISQLAlchemy 2.0 (async)PostgreSQLRedisKafka / RedpandaNext.jsTypeScriptTanStack QueryOpenTelemetryGrafana / Loki / TempoDockerTerraformPlaid APIOpenAI API

Tech stack

Tools I reach for

Languages

  • Python
  • TypeScript
  • JavaScript
  • Java
  • SQL
  • C

Backend

  • FastAPI
  • Django
  • Node.js
  • Express.js
  • GraphQL
  • REST APIs
  • Celery
  • SQLAlchemy

Frontend

  • React
  • Next.js
  • TypeScript
  • Tailwind CSS

Data & Messaging

  • PostgreSQL
  • MySQL
  • MongoDB
  • Redis
  • Kafka / Redpanda
  • Amazon Redshift

Cloud & Infrastructure

  • AWS (EC2, S3, IAM, SES, Lambda)
  • Docker
  • nginx
  • Terraform
  • GitHub Actions

AI / LLM

  • OpenAI API
  • MCP
  • GitHub Copilot
  • Claude
  • Scikit-learn

Education

Academic background

San José State University

Master of Science, Software Engineering

Jan 2026 – PresentSan Jose, CA

Vasavi College of Engineering

Bachelor of Engineering, Computer Science

Dec 2020 – May 2024Hyderabad, India

About

How I think about building software

I care more about whether a system holds up under real conditions than whether it demos well. A login flow that survives a replayed refresh token, an AI feature that degrades to a template instead of crashing when the model call fails, a migration that’s actually been rolled back and forward again before it ships — that’s the part of engineering I find genuinely interesting.

That instinct comes from two places. At S&P Global, I worked on the seam between large language models and enterprise data — teaching tool calls to fetch only the GraphQL fields they actually needed, and rebuilding a nine-hour nightly refresh job as Redshift-backed Python ETL with real retry logic and validation, cutting it to under ninety minutes. Outside of work, I build full systems end to end: FitForge and Meridian each went from a data model on paper to a deployed, containerized application, with the architecture decisions behind them written down as I made them, not reconstructed after the fact.

I’m currently pursuing my MS in Software Engineering at San José State University, building on that same foundation — distributed systems, AI infrastructure, and the kind of backend work that has to be correct before it can be clever.

Contact

Looking for software engineer, backend, full-stack, and AI/LLM engineering roles.

If your team cares about getting the fundamentals right before shipping the interesting part, I’d like to talk.