A project by Dylan

BridgeSphere

Real estate networking platform MVP, contracted to architect whole platform and infrastructure. Primary full-stack engineer from graduate hire to 1.0 launch. (All visuals contain demo data)

BridgeSphere project preview
Project still · BridgeSphere

Role

Primary full-stack engineer

Released

Stack

  • React
  • TypeScript
  • ASP.NET Core 8
  • PostgreSQL
  • Mapbox
  • Azure

See it

The Scenario

A product owner approached me after his real-estate networking project had stalled. The previous developer had left five weeks in with only some wireframes and a few technical documents completed, I came on as the sole engineer on a contract basis. I spent over one year building the application from the ground up: architecture, every line of production code, the roadmap, and day-to-day iteration directly with the founder.

The Role

As a recent grad, this was the deep end: I was responsible for the whole platform.

  • Architecture design and system diagramming
  • Frontend (React SPA) and backend (ASP.NET Core API)
  • Database schema, indexing, geospatial queries, and vector search
  • Matching pipeline design and optimization
  • Authentication, security, and role-based access control
  • Infrastructure, CI/CD, and production operations
  • Requirements gathering, sprint planning, and client demos
  • Direct collaboration with the founder on product direction

What I Built

A monorepo: a React SPA on Azure Static Web Apps, an ASP.NET Core 8 API on App Service, PostgreSQL with PostGIS and pgvector, Mapbox for maps, a FastAPI embedding sidecar, and an Azure Functions image pipeline. Environments promote through Dev, QA, and Prod.

Architecture diagram of the BridgeSphere system

React SPA → App Service API → PostgreSQL/PostGIS/pgvector, with Mapbox, SendGrid, a FastAPI embedding service, and an Azure Functions image pipeline as satellite services, all shipped through a Dev → QA → Prod pipeline.

Matching

Problem:

Early match requests recomputed too much per call: geo candidates, scoring, and embedding similarity. All at once. Under realistic profile volumes, lists felt slow, and repeated dashboard loads made it worse. A full recompute on every request was the wrong default.

BridgeSphere hybrid match pipeline: criteria, geo filter, scorers, semantic embeddings, then rank and cache
Public view of the match pipeline. Weights and score breakdowns stay off the page under NDA.

Constraints

Data freshness mattered. Agents, Clients, and Brokerages may change service zones and preferences often enough that a stale list will harm trust and user experience. Caching the data without a clearly defined invalidation story was showing incorrect matches, based on stale data. Prior to implementing PostGIS, there was a N+1 problem in the code, where all eligble matches within a large radius were called at once. Then scorers and rank/cache would run across this massive data set. I used the haversine formula for all matches within 300km of the primary location of the user, these bugs were causing fetch requests to take up to 20 seconds to match with 50+ paginated agents.

Approach

I treated matching as a pipeline with an expensive tail, and so it was best to optimize the tail-end of the operation:

  • Ran geo filtering early by moving calculations from C# level to PostGIS in PostgreSQL. This caused later stages to work on a much smaller set of data.
  • Ran scoring and semantic similarity only on that filtered set.
  • Cached ranked lists in memory, keyed by requester and match direction.
  • Invalidated the cache on profile and location writes, so edits surfaced on the next meaningful read.
  • Added stricter rate limiting on match endpoints in production so retries and abuse couldn’t amplify cost.

The embedding service ran as a separate FastAPI sidecar rather than inside the .NET API. That kept the main service focused, but it also meant cold starts and timeouts were real failure modes I had to design around in the match path.

Result

Match lists became usable for everyday dashboard traffic, and production held up under normal load. Latency is still an honest constraint at scale: better async refresh and smarter caching are the next levers if the user base grows.

What I’d do next

Move more of the heavy recompute off the request path entirely (queue or background refresh), tighten cache keys around the specific fields that actually change scores, and add load testing (k6) as a release gate on match endpoints.

Hard Parts

  • Multi-role surface. One codebase for clients, agents, and brokerages. Shared primitives (auth, maps, cards, save/unsave) had to stay consistent while each role’s path felt complete.

  • Mapping was a core feature, not simply decoration. This required a great deal of reading the MapBox documentation. Agents/Brokerages draw service zones; clients mark preferred areas. Geography actively drives who shows up in a match list, not just where a pin sits on a map.

  • API iteration and maintainability during requirement evolution. I chose to use the “Strangler Fig Pattern” to slowly migrate toward a cleaner v3 API surface while keeping v2 write paths alive, so production never broke mid-migration.

  • Production ownership. Dev → QA → Prod promotion, DNS, cookie-based auth, rate limits, CORS, and API cold-start issues. Operations was critical part of the engineering job, and was never treated like an afterthought. All code was subject to a strict automated testing and promotion pipeline, using Bash Shell scripting.

Tradeoffs

Decision Tradeoff Justification
Hybrid matching + cache Latency vs data freshness Full recompute on every request was expensive and slow
Dual v2/v3 APIs Complexity vs Continuity I determined it wasn’t feasible to re-write the entire API at once.
Separate embedding sidecar Extra ops Kept the .NET API focused and RESTful.

Reflection

Besides having to learn on the go every day, the biggest lesson I took was that production itself is a feature. Knowing what not to expose in the UI, secrets management, branch promotion, DNS, and ops were just as critical as map demos and matching algorithms.

I went from limited professional experience to owning and engineering a full-stack, multi-environment system end-to-end. This includes all the unglamorous work that separates a basic demo from a real, bonafide product.