DEV Community

Khaja Hussain
Khaja Hussain

Posted on

What Switching From C# to Rust Actually Taught Me

I've spent most of my career writing C#. ASP.NET Core, EF Core, the whole ecosystem — it's productive, well-documented, and I've never had a real complaint about it. This isn't a "C# vs Rust, one wins" post. C# remains one of my favorite languages to build with. This is just about why I got curious about Rust, and what I noticed when I actually rewrote something instead of just reading takes about it.

Why I got curious in the first place

Three things kept pulling my attention:

  1. No GC pauses. C#'s garbage collector is well-engineered, but it still pauses your program at moments it chooses, not you. For latency-sensitive work, that unpredictability is worth understanding better.
  2. Compile-time memory safety. Rust catches null references and data races at compile time instead of at runtime. A different tradeoff, not a "fix" for something broken in C#.
  3. Ownership. People kept describing it as a big deal. I wanted to actually understand why instead of nodding along.

The first two weeks were genuinely hard — I fought the borrow checker constantly, rewriting the same function three times before it compiled. It clicked faster than I expected though, and it left me with a better mental model for shared state in general, one that's helped me even back in C#. I ended up collecting everything I wish someone had told me going in over at Rust Tutorial — more on that at the end, if ownership is the part that's holding you back.

The project: a real-time order tracker

To compare the two properly, I built a small dummy project — a real-time order tracking service. Incoming order events update in-memory state, and connected dashboards get live updates over a WebSocket. It's a common shape: inventory systems, delivery tracking, live ops dashboards.

C# version: ASP.NET Core minimal API, SignalR for the WebSocket push, a ConcurrentDictionary for state.
Rust version: axum for HTTP/WebSockets, tokio as the runtime, state behind an Arc<Mutex<HashMap>>.

Nothing production-grade — just enough of a real workload to notice actual differences instead of comparing "Hello World" benchmarks, which don't tell you much.

What felt different, not better or worse

The frameworks themselves were both pleasant to use. What changed was how explicit I had to be:

  • Shared state. C#'s ConcurrentDictionary just worked — I trusted the library and moved on. Rust made me spell out the Arc<Mutex<...>> at every point it was touched. More typing, but I came away understanding my own concurrency model better.
  • Errors. A malformed event in the C# version could throw from a background task and, if I'd missed a try/catch, fail quietly. Rust's Result made every fallible step something I had to explicitly acknowledge.
  • Nulls. "Order not found yet" was a null check I could forget in C#. In Rust it's Option, and the compiler won't let it slide.

None of this means Rust is "better" — it just made assumptions in my C# code more visible, which was uncomfortable at first and useful by the end.

Quick, informal numbers (not a real benchmark)

Full transparency: this was a five-minute wrk run on my own laptop, not a controlled test environment. Don't read too much into the exact figures — but the general pattern lined up with what's commonly reported elsewhere too.

C# (ASP.NET Core) Rust (axum)
Idle memory footprint ~110 MB ~9 MB
Cold start time ~1.2s ~40ms
Requests/sec (simple load test) ~9,000 ~34,000
p99 latency ~42ms ~6ms
Deploy artifact App + .NET runtime Single ~6MB binary

The gap narrowed once .NET's JIT fully warmed up under sustained load — it's genuinely competitive once hot. Rust's edge was most consistent in memory footprint and tail latency, which tracks: no GC means no surprise pause landing in your worst-case requests.

Where Rust felt rougher

To keep this balanced:

  • Compile times grew noticeably slower than C#'s as the project did.
  • Ecosystem gaps — some things .NET gives you out of the box (certain auth patterns, mature ORMs) took more assembly in Rust's crates.
  • The learning curve is real. Not the right moment to introduce it if your team is shipping next week.

When I'd reach for which

Situation I'd reach for
Typical CRUD app / internal business tool C# — EF Core and the .NET ecosystem get you there faster
Team is already deep in .NET, tight deadline C# — the right call, no reason to add a learning curve under pressure
Real-time systems where latency predictability matters Rust — no GC pause means a flatter tail latency
Memory-constrained environments (containers, edge, embedded) Rust — the footprint difference is real and adds up at scale
Need a small, dependency-free deployable binary Rust — one binary, nothing else to ship
Rich enterprise integrations (auth providers, ORMs, admin tooling) C# — still the deeper batteries-included ecosystem
Want to learn something that reshapes how you think about memory and concurrency Rust — worth the rough two weeks even if you never ship it

So, am I dropping C#?

Not even close. For CRUD apps and business logic, C# is still one of the most productive languages I know, and that hasn't changed. What changed is that I now have another tool for the specific cases where predictable latency and a small footprint actually matter — and Rust earned that spot honestly.

If you're curious about Rust coming from C

If you want the official deep reference, The Rust Book is where most of the Rust community points beginners first. Alongside that, I also put together a helpful website while working through ownership and borrowing myself — plain explanations, runnable examples, nothing assumed: Rust Tutorial.

If you're a C#/.NET dev thinking about giving Rust a try, either one is a solid place to start.

Have you made a similar jump — from C#, Java, Go, or anywhere else? Curious what surprised you.

Top comments (0)