Work

Aussie EcoLens

A wildlife observation platform split across two clouds on purpose: writes land on AWS, reads are served from Azure, with CQRS holding the seam together. MegaDetector v5a screens every upload before SpeciesNet classifies it.

AWSAzurePythonTerraformDockerKubernetesMegaDetectorSpeciesNet
2025Monash FIT5225 · four-person team
Role
ML primary, API secondary
Team
4 engineers
Accuracy
100% top-1 on 26 ground-truth images
Runtime
Graviton2 (arm64)

Why two clouds

A single-cloud build would have been faster to ship and less interesting. Splitting the write path (AWS) from the read path (Azure) forced us to be explicit about where consistency actually mattered — which turned out to be a much smaller surface than we assumed going in. Uploads, detection and classification run as AWS Lambda behind API Gateway; the read model is projected into Azure and served from there.

The detection pipeline

Every image passes through MegaDetector v5a first, which is cheap and only answers one question: is there an animal in this frame. Anything that clears the threshold goes to SpeciesNet for species-level classification. Running the cheap model first meant we weren't paying classification cost on empty frames, which is most of what a camera trap produces.

arm64, and what it cost

The whole inference path is containerised and runs on Graviton2. Getting the model dependencies to build cleanly for arm64 was the least glamorous and most time-consuming part of the project — several of the vision libraries had no arm64 wheels, so they compiled from source in the image build. The payoff was a meaningful drop in per-invocation cost.

Next