I added AI background removal to my image converter in a week, in Rust, no Python A solo developer added AI background removal to Convertify, a free image converter, in one week using only Rust and no Python. The backend runs ONNX models natively via the ort crate, avoiding the need for a separate Python process. Challenges included handling a 171 MB model file and adapting to ort's non-Send+Sync errors and mutable session requirements. Part of an ongoing build-in-public series on Convertify, a free image/file converter I build solo. This week: background removal. The honest version, with the walls I hit. Most "remove image background" tutorials end with pip install rembg and a happy screenshot. Mine started with a constraint: my whole backend is Rust, and I did not want to bolt a Python process onto it just to run one model. Here is how the week went. The good parts, and the three or four times I stared at a compiler error wondering if the constraint was worth it. Convertify is a free image converter. The backend is Rust + Axum + libvips , the model has to run CPU-only on a modest VPS , and there is no GPU anywhere in the budget. The obvious path for background removal is rembg , which is excellent, but it is Python and ships as a separate server process. Adding it would mean a second runtime, a second thing to deploy, a second thing to crash at 3am. So the question for the week was simple: can I run the same models rembg uses, but natively in Rust? Short answer: yes. rembg is, under the hood, just ONNX models plus some image pre and post processing. The models u2net, isnet, silueta are all .onnx files. If I can run ONNX in Rust and do the image work in libvips which I already have , there is no Python in the picture at all. The pipeline for background removal is not magic, it is five boring steps: Steps 1, 4, 5 are libvips, which I already use everywhere. Step 3 is ONNX Runtime via the ort https://github.com/pykeio/ort crate. Step 2 is a tight Rust loop. No Python anywhere. dependencies ort = { version = "=2.0.0-rc.12", features = "download-binaries" } The download-binaries feature pulls a CPU build of ONNX Runtime at build time, so there is nothing to install on the box. That alone deleted half the "deploy a Python service" anxiety. I grabbed isnet-general-use.onnx from the rembg releases, expecting ~44 MB. What landed was 171 MB . My first thought was a broken download or an HTML error page renamed to .onnx . Quick check: file models/isnet-general-use.onnx head -c 200 models/isnet-general-use.onnx | xxd | head The header showed a real pytorch 1.13.1 signature and tensor names like input image and conv in.weight . So it was a valid ONNX model, just heavier than the name suggested. Lesson: verify the file is actually what you think before you spend an hour debugging "why is RAM so high." ort errors are not Send + Sync First compile against anyhow and I get hit with this: the trait Sync is not implemented for NonNull