DEV Community

Cover image for Why I Fell in Love with Rust’s Memory Model (Even Though It’s Hard)
Kamal Rhrabla
Kamal Rhrabla

Posted on

Why I Fell in Love with Rust’s Memory Model (Even Though It’s Hard)

I’ve worked with languages like JavaScript and Go, and I enjoyed both for different reasons.

JavaScript gave me speed and flexibility. Go gave me simplicity and practical concurrency.

Then I met Rust and at first, it felt difficult.

But once I understood how Rust handles memory without a garbage collector, I fell in love with it.

Memory Safety Without a Garbage Collector

Most modern languages solve memory management with a garbage collector (GC).

A GC periodically finds memory that is no longer used and frees it automatically.

Rust takes a different path:

  • No runtime garbage collector
  • No manual free() like in C
  • Memory safety guaranteed at compile time (in most cases)

Rust uses three core ideas:

  1. Ownership
  2. Borrowing
  3. Lifetimes

These rules are checked by the compiler before your program runs.

1) Ownership: One Owner at a Time

In Rust, every value has a single owner.

When the owner goes out of scope, Rust automatically drops the value and frees memory.

{
    let s = String::from("hello");
    // s owns the string memory here
} // s goes out of scope, memory is freed automatically
Enter fullscreen mode Exit fullscreen mode

This avoids memory leaks and double-frees in normal code paths, without needing a GC pause.

2) Borrowing: Use Data Without Taking Ownership

Instead of copying or transferring ownership all the time, Rust lets you borrow references:

  • Immutable borrow: &T
  • Mutable borrow: &mut T

But Rust enforces strict aliasing rules:

  • Many immutable references OR
  • One mutable reference
  • Not both at the same time

This rule prevents data races at compile time.

3) Lifetimes: References Must Always Be Valid

Lifetimes describe how long references are valid.

Often, Rust infers lifetimes automatically. When needed, you can annotate them.

This helps prevent dangling references references to memory that no longer exists.

How Rust “Behaves” in Practice

When writing Rust, you feel the compiler acting like a strict mentor:

  • “Who owns this value?”
  • “How long does this reference live?”
  • “Are you mutating while also sharing?”
  • “Could this reference outlive its data?”

At first, this feels like friction.

Later, it feels like protection.

The compiler catches entire classes of bugs before runtime:

  • Use-after-free
  • Double free
  • Null-like reference misuse
  • Data races in concurrent code

Why It Feels Hard (Especially Coming from JavaScript and Go)

From JavaScript to Rust

JavaScript is highly dynamic and forgiving.

You can move fast, but many errors appear at runtime.

Rust is the opposite: strict upfront, safer later.

From Go to Rust

Go has garbage collection and a simpler mental model.

Rust asks you to think more deeply about ownership and borrowing.

In Go, many programs compile quickly and run fine, but some memory/concurrency issues emerge later.

In Rust, many of those issues are rejected during compilation.

Why I Fell in Love with Rust

Even though Rust is harder, I love it because:

  • It gives low-level control with high-level safety
  • It avoids GC pauses while staying memory-safe
  • It makes concurrency safer by default
  • It turns the compiler into a collaborator
  • It teaches better engineering habits

Rust doesn’t just help me write code that works.

It helps me write code I can trust.

Final Thought

Rust has a steep learning curve especially if you come from JavaScript or Go.

But once ownership and borrowing click, the difficulty starts to feel meaningful.

For me, Rust changed how I think about memory, correctness, and software design.

That’s why I fell in love with it.

Top comments (0)