Maricopa County is home to over 60 school districts and tens of thousands of educators. The Superintendent’s office runs professional development programs — certifications, workshops, coaching engagements — but connecting the right educator to the right opportunity had historically been a manual, spreadsheet-driven process.
I was brought in as the sole developer to build a platform that could automate this matching work using AI and serve as the infrastructure for educator credentialing across the county.
What I Built
Starting from a product brief and a whiteboard, I designed and built the entire platform: a Python/FastAPI backend, a PostgreSQL database, a GraphQL API layer, and a TypeScript/React frontend — all running on AWS.
The AI matching engine is the core of the platform. Educator profiles — including teaching subjects, grade levels, certifications held, and professional goals — are embedded as 1536-dimensional vectors using the OpenAI embeddings API and stored in PostgreSQL using the pgvector extension. Opportunity listings are embedded the same way. Matching runs as a vector similarity search, surfacing the most semantically relevant opportunities for each educator rather than relying on keyword matching or manual tagging.
The data model covers 80+ REST endpoints and GraphQL resolvers handling educator profiles, district rosters, opportunity listings, application workflows, and credentialing records.
The migration involved moving the backend from Node.js/GraphQL to Python/FastAPI with SQLAlchemy 2.0 and Alembic — maintaining dual data-fetching during the transition period (Apollo + React Query) to avoid a hard cutover.
A real-time messaging layer supports communication between educators and program coordinators built on WebSocket with a notifications system for application status changes.
Matching System Evolution
V1 — Deterministic weighted scoring
The first version of the matching engine relied on a hierarchical taxonomy: each user profile was scored against opportunities through a deterministic weighted system that compared standard, content area, and subject levels. Pre-calculated profile matches were stored across all content areas, giving fast lookups but with O(n) storage costs that scaled poorly as the catalog grew.
The V1 stack was serverless on AWS: API Gateway fronted a TypeScript Lambda that wrote to DynamoDB. It was fast to ship but the key-value model made evolving the matching schema painful, and Lambda cold starts hurt the matching endpoints once the catalog grew.
V2 — Embedding-based semantic matching
V2 replaces the hand-tuned scoring with vector embeddings. Profile attributes — job title, company, intro, and keyword defaults derived from profile details — are concatenated and embedded via the OpenAI embeddings API. Matching becomes a vector similarity search, letting users still customize keywords while semantic search handles the heavy lifting. No precomputed match tables; storage stays bounded as the catalog scales.
V2 moved the runtime onto AWS App Runner with a Python/FastAPI service, and swapped DynamoDB for PostgreSQL + pgvector. The relational model handles the richer credentialing schema cleanly, and pgvector colocates vector similarity search with the rest of the data — no separate vector store to operate.
Technical Highlights
- OpenAI embeddings (1536-dim) + pgvector for semantic educator-opportunity matching
- 80+ REST/GraphQL endpoints across educator, district, opportunity, and credentialing domains
- Python/FastAPI + SQLAlchemy 2.0 backend with Alembic migrations
- Live migration from Node.js/GraphQL to Python backend with dual data-fetching during transition
- Real-time messaging and notification system via WebSocket


