← All work

3D Structural Model Platform

A web platform for a structural engineering consultancy that parses and renders JSAF structural models in 3D, including files up to 600 MB.

Role
Software Architect & Backend Lead
Period
Aug 2025 – Present
Client
Structural engineering consultancy · in production
  • C#
  • ASP.NET Core
  • PostgreSQL
  • React
  • TanStack Query
  • Three.js
  • Web Workers
  • GCP
  • Pub/Sub
  • Render
  • Terraform

Context

The consultancy needed to review structural models in the browser, without desktop software. I was the solution architect on a team of 5, wrote most of the backend and led the major architecture refactors. Since October 2026 I maintain the platform.

The problem

Models arrive as JSAF files of up to 600 MB. Parsing them on the request path timed out, and rendering them naively froze the browser and ran out of memory.

Architecture

Follow the flow as you scroll. Each step shows what it does.

01 UploadJSAF · up to 600 MB02 Object storageCloud Storage03 MessagePub/Sub04 Parser workerASP.NET Core05 Model dataCloud SQL · PostgreSQL06 APIASP.NET Core07 Web WorkersLazy loading08 3D renderThree.js01 UploadJSAF · up to 600 MB02 Object storageCloud Storage03 MessagePub/Sub04 Parser workerASP.NET Core05 Model dataCloud SQL · PostgreSQL06 APIASP.NET Core07 Web WorkersLazy loading08 3D renderThree.js
  1. UploadThe browser uploads the model file directly.
  2. Object storageRaw files are stored once and never block the API.
  3. MessageA message hands the work to a worker.
  4. Parser workerParses the JSAF model off the request path.
  5. Model dataParsed elements and metadata, ready to query.
  6. APIServes the model in chunks to the browser.
  7. Web WorkersGeometry is built off the main thread and streamed in.
  8. 3D renderThe engineer explores the structure in the browser.

GCP · Cloud Storage · Pub/Sub · Cloud SQL — all in Terraform

resource "google_storage_bucket" "models" {
  name = "structural-models"
}

resource "google_pubsub_topic" "parse" {
  name = "model-parse"
}

resource "google_sql_database_instance" "main" {
  database_version = "POSTGRES_16"
}

What I did

  • Designed a server-worker architecture: uploads go to Cloud Storage and a Pub/Sub message triggers a parser worker.
  • Wrote most of the ASP.NET Core backend and led the big refactors when the architecture changed.
  • Optimized Three.js rendering with Web Workers, lazy loading and careful memory management.
  • Defined the GCP infrastructure in Terraform: Cloud Storage, Cloud SQL and Pub/Sub.
  • Ran discovery sessions, demos and feedback loops with the client to validate scope and decisions.

Key decisions

Never parse on the request path

The API only accepts the upload and returns. A Pub/Sub message hands the work to a worker, so a 600 MB file can’t time out a request or slow down other users.

Keep the main thread free

Geometry is prepared in Web Workers and loaded progressively, so the page stays responsive while the model streams in.

Terraform for a client-owned platform

The client owns the infrastructure as code. Any engineer can recreate or change it, which made the handover to maintenance straightforward.

Results

  • 600 MBmodels processed in ~50 s
  • 5engineers on the team, architecture led by me
  • Livein production and growing