
I’ve been fascinated by Rust ever since I discovered it could solve many of the memory safety and concurrency challenges I encountered in programming games and web services while in college. In my free time I learnt about the language and had grown a love for it and started talking about it to anyone who would listen.
That seemed to have worked well, because in December of 2023, a Director at RBC (Royal Bank of Canada) tapped me on the shoulder and asked if I'd be interested in giving a Tech Talk on Rust.
I couldn't say yes fast enough!
The goal was simple yet ambitious: introduce Rust to my fellow employees and spark a conversation about integrating the language into our tech stack. Over the course of a month, I pieced together a 30-minute presentation, focusing on what I consider the three key features that make Rust shine: a strong type system, the borrow checker and in result of those two features, fearless concurrency.
This is that presentation.
The actual slides, programming in markdown using marp.
Learning to love the Rust Propaganda
Understanding why Rust is the most loved and admired programming language today.
It's important to state that you aren't going to learn rust by viewing this presentation, you're better off going through the Rust Book for that. Instead I'll focus on the following areas:
- A brief history of Rust
- My top 3 Rust features
- The Rust community
What is Rust?
Rust is a general purpose programming language that exceeds in systems and embedded systems programing. That means it's a smart choice for using it to develop applications such as Operating Systems, Development tools, Databases, Drones and Medical Devices. This is because of its focus on memory safety. The language helps you build resilient systems on the abstraction of a computer system.
Rust doesn't need to be used only on these low level systems, it also has extensive libraries and support for being used to develop application as well. Things like Web Servers, Game Engines and Web Browsers are all examples of what have also been built using the Rust programming language.
You don't need to take my word for it, lot of organizations are using Rust to develop new software. Take a look at some of these articles detailing where and how it's being used:
- Microsoft is spending $10 Million to use Rust across their engineering system
- Google has pledged $1 Million to improve interoperability with C++
- AWS build the Firecracker virtual machine in Rust
- Cloudflare, Figma, Meta, and many more
The story behind Rust
The Rust programming language started as a personal project in 2006 by Graydon Hoare. He was 29 year old developer work at Mozilla. One day after a long days work, he got home and noticed that the elevator wasn't working again; The software had crashed.

He reflected on this moment during his climb up to the 21 floor. How software developers couldn't make an elevator work without it crashing. At this very moment, Rust was born, "over-engineered for survival".
Ever since then, Rust adoption has been growing.
In 2009, Mozilla Research sponsored the project for development of their servo web browser engine. Although it had some bumps along the way (it started with a garbage collector believe it or not), in 2015, it finally had it's 1.0 release.

The goal of the Servo project was to rebuild and rethink what a browser was capable of while creating a safer browser. CPU's with more cores were being released and there was an idea that you can use those to make a safe and fast multithreaded web browser architecture. The idea being that using Rust for this type of development meant that it could eliminate vulnerabilities in managing memory and data races.
Influences on Rust
Rust is not an original language though. It borrows many concepts created in other programming languages. For example, it borrows
- Algebraic data types and pattern matching from OCaml
- References, Smart pointers, move semantics (and more) from C++
- Optional bindings from Swift
- Messaging passing and thread failure handling from Erlang
- Hygienic macros from Scheme
- And many more
With that, I think I can talk about my 3 favourite features of Rust.



The 3 features you wish your language had
My marketing to convince you python is the wrong choice
💪 Strong Typing
A strong type system makes issues seen in languages like javascript impossible. For example, let's take the following javascript code:
assert(1 + "2" == 12)
In Rust, the string type needs to be converted to a number before doing the addition. A Rust developer may program that same test like so:
assert_eq!(1 + "2".parse::<u32>().unwrap(), 3)
You'll notice that in Rust, we can't mix and match variables because it's strictly typed, guaranteeing at compile time that our program is valid and type safe. The call to unwrap()
is telling rust to compiler to trust us. Had we not passed in 2
, the program would panic and exist before executing the assert.
It can also require we check if something exists
For example, take the following Python example:
dictionary = {}
variable = dictionary["does_it_exist?"]
do_foo(variable)
The above example shows us getting a value from a dictionary, but we need to choose to check it. This can cause us to program logic expecting the variable exists. It can cause subtle bugs as our programs grow larger and larger.
In Rust, that's impossible, we need to explicitly handle the possibility that our value, might not exist the moment we program the application.
let dictionary = HashMap::new()
if let Some(value) = dictionary.get("does_it_exist?") {
do_foo(value)
}
This results in Rust programmer thinking up front with what to do with their errors and where they might occur.
And it will always guarantee memory points at something
For example, in the Go programming language we can program in a segfault and compile our program successfully. For example:
var pointer *int
number := *pointer // 🚨 Segault here
fmt.Println(number)
This compiles. In Rust, that's impossible without explicitly creating an unsafe
block, therefore, much less likely to happen.
Therefore, strong typing is a benefit because it moves the error checking from runtime, to compile time. There is no longer a need to test your programming running because the type system will prove if the program works ahead of time!
Rust is forcing you to put all these types around your program which act like small unit tests. They bake your assumptions about the code, into the program.
Comparing this to a dynamic language where you need to assume you have the correct variables, and the need to write unit tests to prove a variables that is a different type doesn't crash your program.
Strong typing makes writing correct code - code that does what you expect - easier. By spending more time up front coding, you'll no longer need to spend more time debugging your code at runtime.

🤓 The borrow checker
The borrow checker is an advanced type checking system in Rust that attempts to determine the life cycle of all the variables inside of your program. It does this by doing the following:
- Tracking Ownership
- Checking Borrows
- Validating Lifetimes

If a program can't pass the borrow checker, it doesn't compile. This enforces the idea that when you program an application in Rust, and it compiles, it should be memory safe and type safe! Let's take an look at what these 3 features mean when developing your program:
Ownership
For ownership, it enforces the idea that there can only be one owner of a variable at any time. For example:
struct Example {}
fn passing_ownership(obj: Example) {}
fn main() {
let example = Example {};
passing_ownership(example); // <-- Move of `example`
print!("{}", example) // ERROR! example is already owned
}
Because of the ownership rule, this program doesn't compile because when we call passing_ownership
, we are moving it into the function and so it will no longer exist for it to be printed on the next line down.
Borrowing
Borrows in Rust can happen multiple times to create multiple readers of existing data. For example:
let data = 5;
let first_borrow = &data;
let second_borrow = &data;
println!("First borrow: {first_borrow}");
println!("Second borrow: {second_borrow}");
Here, we are taking a reference to our data. Because we are only going to read from it, we can make many variables pointing to the same data. But what if we wanted to also write to data
from one of our references? For example:
let data = 5;
let first_borrow = &mut data;
let second_borrow = &mut data; // <-- 🚨 Error here
// ERROR: cannot borrow `data` as mutable more than once at a time
println!("First borrow: {first_borrow}");
println!("Second borrow: {second_borrow}");
That isn't possible! This is because data can only have one writer at a time. In this case, first_borrow
is the only variable that can write to data
, therefore, we can't create another mutable reference.
Lifetimes
Lifetimes validate that reference you create from your variables are only borrowed within the scope of their life throughout the program. For example:
// Must be explicit that we are borrowing a string for the lifetime of 'a
structure StringSlice<'a>(&'a str);
let message = "hello, world";
let slice = StringSlice(&message[7..]); // Borrow a "slice" of a string
println!("{}", slice.0); // print "world"
Here we should that I can create a new structure that borrows the lifetime of the message
variable, therefore, I'm able to use it to print world
out to the console.

Benefits of the borrow checker
Using ownership, borrowing and lifetimes allows Rust to enforce that at all times there is only ever 1 writer and multiple readers of a variable.
This provides safety from data races ever showing up in your program. It guards common errors from occurring as well like move after free. That's where memory has been released by the operating system but a reference to that part of the memory still exists in your program.
The borrow checker and strict typing work together to show clear ownership of variables within a program. With Rust, it's easy to determine if you are altering a reference or the underlying variable.
😏 Fearless concurrency
Because of lifetimes and a strong type system, we can push the performance of our programs safely. Gone are the days of accidentally referencing a global in python and using it in multi-threaded code. Rust protects you from doing just that. For example, let's take a look at a program that fails to compile because ownership and lifetime principles:
let mut = thread_list = vec![]
let mut num = Box::new(0);
for _ in 0..10 {
thread_list.push(thread::spawn(move || *num += 1)); // <-- 🚨 Error
}
let _ = thread_list.into_iter().map(Joinhandle::join);
println!("{num}");
In the program above, we create a Box
(a unique pointer) and we want to increment it to 10. This is done by using a loop that spawns a thread which increments our boxed pointer for us.
However, the program fails to compile saying that num
value is moved into the closure and doesn't exist on the next iteration of the loop. This is because the ownership of the variable is moved into the thread's scope. When the for loop goes into the second iteration, the num
variable no longer exists in the scope anymore because it was moved.
Instead, if we wanted to actually make a multi-threaded program to add up an integer, we'll need to make a copy of the variable which we could then pass the ownership of into the thread's scope. We need a shared pointer to our data!
let mut list = Vec::new();
let counter = Arc::new(Mutex::new(0)); // notice this isn't mut
for _ in 0..10 {
let cloned_counter_pointer = counter.clone() // create new ownership
list.push(thread::spawn(move || {
// Wait for us to `own` the data
let mut locked_counter = cloned_counter_pointer.lock().unwrap();
*locked_counter += 1; // increament the data
})); // Release ownership of the data
}
let _ = list.into_iter().map(Joinhandle::join);
println!("{}", *counter.lock().unwrap());
In the above example, we use an Arc
Atomic Referenced Counter pointer. This pointer is safe to share across threads. However, an Arc
does not allow any copy of the pointer to gain mutable access to the data. Therefore, to change it, we need to wrap it in a Mutex
. This is because a Mutex
will enforce that data can only be accessed by one thread at a time.
The confirms to the rust program that only one writer exists, and so, we are able to increment the counter. Thus at the end of the program, we get our expected value of 10!
Benefits of concurrency
By relying on the borrow checker, we can scale our code to use the full potential of our CPU without being scared we are programming data reaches into our code. We can fearlessly distribute our work across multiple threads and reap the increased performance in our application.
With Rust, you can sleep easy knowing that when a Rust program compiles, it means 99% of the time, it will work exactly the way you expect and won't wake you up at 1AM in the morning.

🚀⚡️ Lighting Round ⚡️🚀
There really are too many good things to say about Rust to fit into a short, 30 minute. So I decided that I'll try and list off a couple of the other features that I like about the language, such as:
Amazing Error messages
Rust error messages help you understand its complex systems by providing robust explanation of why your code isn't compiling. Let's take a multi-threaded example, but this time using a Rc
(Reference counted pointer).
let a = Rc::new(10);
let b = a;
std::thread::spawn(move || {
println!("{}", b);
});
When trying to compile we can see that Rc
can't be sent between threads safely.
➜ example git:(main) ✗ cargo run
Compiling example v0.1.0 (/user/Rust-Presentation/example)
error[E0277]: `Rc<i32>` cannot be sent between threads safely
--> src/main.rs:10:24
|
10 | std::thread::spawn(move || {
| ------------------ ^------
| | |
| _____|__________________within this `[closure@src/main.rs:10:24: 10:31]`
| | |
| | required by a bound introduced by this call
11 | | println!("{}", b);
12 | | });
| |_____^ `Rc<i32>` cannot be sent between threads safely
From the error, you can read that the reason for the program fails compiling because an Rc
can't be moved between threads safely.
Generics
Rust has this idea of traits (similar to interfaces, but not the same) that types can inherit. Once done, they can be used in functions like the following:
fn print_to_console<D: std::fmt::Display>(d: D) {
println!("{d}");
}
fn main() {
print_to_console("hello, world");
print_to_console(42);
print_to_console(true);
}
And when compiled has the following output:
➜ example git:(main) ✗ cargo run
hello, world
42,
true
Testing in documentation
If you have ever had documentation drift in your code, Rust can help with that by testing your documented assumptions are correct for a function, like so:
/// ```
/// use lib::add;
/// assert_eq!(add(41, 1), 42) // <-- this code runs on `cargo test`!!!
/// ```
pub fn add(left: usize, right: usize) -> usize {
left + right
}
This validates that our documentation always confirms that our function works as expected.
➜ example git:(main) ✗ cargo test --doc
running 1 test
test src/lib.rs - add (line 3) ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.26s
Rust Macros
Rust macros can generate code so that you can type less. For example, creating a CLI in Rust is super easy thanks to clap
package!
/// Simple program to greet a person
#[derive(Parser, Debug)
#[command (author, version, about , long_about = None)]
struct Args {
/// Name of the person to greet
#[arg(short, long)]
name: String,
/// Number of times to greet
#[arg(short, long,deafult_valut_t = 1}0
count: u8,
}
It's pretty cool that a little bit of markup in your Rust code can then produce the following output:
➜ example git:(main) ✗ cargo run -- --help
Simple program to greet a person
Usage: example [OPTIONS] --name <NAME>
Options:
-n, --name <NAME> Name of the person to greet
-c, --count <COUNT> Number of times to greet [default: 1]
-h, --help Print help
-V, --version Print version
But that's not all you can do with macros!
Ever want to validate your SQL queries at compile time? Yup, Rust can do that too thanks to sqlx
crate.
sqlx::query!(r#"SELECT id, description, done FROM todos ORDER BY id"#)
.fetch_all(pool)
.await?;
And there lots more like
- Needing to deal with JSON, XML, YAML, etc? Use the popular
serde
crate - Love the builder pattern? There's a macro for that!
derive_builder
🤯🤯🤯 MORE MACROS WTF?!?!?! 🤯🤯🤯
WAIT YOU WANT TO PROGRAM YOUR NODE AND PYTHON PACKAGES IN RUST TOO!! 🚀 (Respect 😏 btw). Well let me tell you, RUST CAN DO TAHT TO 🧠.
- Don't like using
react
cause it's slow? useyew
crate to program your frontend. - Need to go fast but you are using Javascript? No worries, use
wasm-pack
to deploy your Rust code as an npm module! - Using python? Ditch the training wheels and go fast by using Rust to build a native python extension module using
pyo3
.
🚨BUT WAIT! THERES MORE! 🚨
Rust doesn't just stop there, it also has
- A powerful Trait system
- Zero cost abstractions
- Iterators
- Channels and messaging passing
- cross platform support
async
/await
- New releases every 6 weeks
- update language in one command
- Built in package manager support
- AND SO MUCH MORE!
Learning and staying in the loop
If you've made it this far, you probably have a want to continue learning Rust. I think you are making a smart decision and to help you on your journey, I would recommend the following learning material.
- Rust book: where you can learn the basics (and advanced material) of the language
- Google Comprehensive Rust: Googles introduction to Rust
- Learn Rust with entirely too many linked lists: to understand ownership and lifetimes
- Jon Gjengset @jonhoo: Youtube channel covering advanced Rust
- Proc Macro workshop: Example of how to make your own procedural Rust macros
- Mini-LSM: A tutorial on build a log structure merge tree database
Sometimes just learning isn't enough. It's a good idea to supplement your learning with content created by professionals as well. For that, you could follow some blogs, YouTube channels and podcasts:
- This week in Rust - A weekly newsletter on Rust articles made by the community
- Crustacean Station - Podcasts on Rust the language and it's projects
- Rust - YouTube channel with talks and project
- Small Cult Following - about the language and it's development
- Yoshua Wuyts - A lot of discussions about everything Rust
- Faster than lime - Discussion on Rust and general programming
Finally, if this didn't convince you to learn more Rust, maybe some other presentation on Rust will do a better job:
- Considering Rust by Jon Gjengset
- Unlocking Rust's power through mentorship and knowledge spreading, with Tim McNamara - who led Rust education across Amazon

So, what was the Result?
An exciting end to a great Rust presentation
So, on a crisp morning in January, I joined a Webex call, excited (and a bit nervous) to see who would show up from across the bank. The participant slowly list grew as I started my presentation. By the time I started speaking, more than 400 people had joined, a far bigger audience than I ever expected.
I dived into the slides, explaining how Rust ensures memory safety through its unique ownership model, how it makes concurrency less daunting, and how there are too many features to speak of.
Thanks to plenty of practice, the flow felt smooth. I could sense the energy in the virtual room: heads nodding and questions popping up in the chat. After I wrapped up the core content, we launched into a Q&A session. For the next 30 minutes, questions poured in about the feasibility of blending Rust into our existing codebases, the learning curve for new developers, and the long-term maintenance benefits. It was exhilarating to see so much curiosity, and it confirmed that Rust had the interest of some of the people across the bank.
Looking back, I’m thrilled with how the presentation turned out. It was a personal milestone—I learned a lot about public speaking and about how to articulate the practical benefits of a technology I’m genuinely passionate about. Employees from different parts of the organization reached out to me after words to talk about their own journey on using Rust in their own time.
One director I talked with said that when he asked his team, 5 of his 10 employees said they'd be interested in using it during their full-time work. That got me thinking what my team would think about adopting rust. When I brought it up I was told by two of my co-workers:
Well, one step forward, two steps back, but onwards I march spreading the good word.
In Conclusion
If you’re thinking about introducing Rust to your own team or company, I can’t recommend it enough. Sometimes, all it takes is one spark to ignite a broader conversation around new technology. And who knows? You just might find yourself in front of a virtual crowd of 400 enthusiastic colleagues, championing the next big thing in programming.