<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marc Cámara</title>
    <description>The latest articles on DEV Community by Marc Cámara (@mcamara).</description>
    <link>https://dev.to/mcamara</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F97693%2Fc9512d7d-00aa-44e8-ad9b-7e71689631f6.jpeg</url>
      <title>DEV Community: Marc Cámara</title>
      <link>https://dev.to/mcamara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mcamara"/>
    <language>en</language>
    <item>
      <title>A Practical Guide to Rust Smart Pointers</title>
      <dc:creator>Marc Cámara</dc:creator>
      <pubDate>Fri, 16 Jan 2026 11:02:00 +0000</pubDate>
      <link>https://dev.to/mcamara/a-practical-guide-to-rust-smart-pointers-5g5a</link>
      <guid>https://dev.to/mcamara/a-practical-guide-to-rust-smart-pointers-5g5a</guid>
      <description>&lt;p&gt;Smart pointers are one of Rust's most powerful features for managing memory and ownership. Rust has a lot of smart pointers, so keeping track of all of them is a daunting task. &lt;/p&gt;

&lt;p&gt;In this article, I'll walk through the most common smart pointers you'll encounter in Rust, with practical examples of when to reach for each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rc
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/rc/struct.Rc.html" rel="noopener noreferrer"&gt;Rc&lt;/a&gt; is one of the most commonly used smart pointers in Rust. Use it when ownership is genuinely shared between multiple owners and lifetimes become complex. &lt;code&gt;Rc&lt;/code&gt; keeps a reference count of the number of owners of the data (basically, when a &lt;code&gt;Rc&lt;/code&gt; variable is cloned, the reference count is incremented). When the reference count reaches zero, the data can be safely deallocated. &lt;code&gt;Rc&lt;/code&gt; does not implement the &lt;code&gt;Send&lt;/code&gt; or &lt;code&gt;Sync&lt;/code&gt; traits, so it cannot be sent to other threads, &lt;code&gt;Arc&lt;/code&gt; fixes it...&lt;/p&gt;

&lt;h2&gt;
  
  
  Arc
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/sync/struct.Arc.html" rel="noopener noreferrer"&gt;Arc&lt;/a&gt; is probably the most popular smart pointer across all Rust projects. Pretty similar to &lt;code&gt;Rc&lt;/code&gt;, use it when you need to have multiple owners of the same data in different places of your app and there is no way to know at compile time when this data can be freed. The difference between &lt;code&gt;Rc&lt;/code&gt; and &lt;code&gt;Arc&lt;/code&gt; is that &lt;code&gt;Arc&lt;/code&gt; implements the &lt;code&gt;Sync&lt;/code&gt; and &lt;code&gt;Send&lt;/code&gt; traits, so it can be sent to other threads. &lt;/p&gt;

&lt;h3&gt;
  
  
  Quick note from the developer
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;You are looking at one of the articles on my &lt;a href="https://marccamara.com" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt;, please support me by visiting it, thanks!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Box
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/boxed/struct.Box.html" rel="noopener noreferrer"&gt;Box&lt;/a&gt; is simpler than it might seem at first. It allocates data on the heap instead of the stack, which is useful in a few specific scenarios, especially when you have multiple implementations of a trait, but you don't really know which one will be used at runtime. Like in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;consoles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Nintendo&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sony&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;console&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;consoles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="nf"&gt;.play&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Box also works well when a struct contains a field of its very same type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Box breaks the infinite size chain&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;node2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;node1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  RwLock
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html" rel="noopener noreferrer"&gt;RwLock&lt;/a&gt; is great too! Thread safety, mutable global state that can be shared across the app and it can be read from multiple places at the same time (locks on reading are not exclusive). The only downside is that when you request a write lock while there is a &lt;code&gt;RwLock&lt;/code&gt; guard in place, the request for that write lock will block until the guard is dropped, but that's the price to pay for data consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mutex
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" rel="noopener noreferrer"&gt;Mutex&lt;/a&gt; is similar to &lt;code&gt;RwLock&lt;/code&gt; but a bit simpler. The difference is that &lt;code&gt;Mutex&lt;/code&gt; locks the data whether it is being written or read. This means that if you have a &lt;code&gt;Mutex&lt;/code&gt; guard in place, you cannot read the data until the guard is dropped. Use &lt;code&gt;Mutex&lt;/code&gt; when your data needs exclusive access for both reads and writes, or when you want simpler semantics without worrying about read/write lock distinctions. In my particular case, I usually find myself using &lt;code&gt;RwLock&lt;/code&gt; most of the times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/cell/struct.Cell.html" rel="noopener noreferrer"&gt;Cell&lt;/a&gt; is a mutable container that can be used in a single-threaded context. It allows you to mutate the value inside without having to worry about thread safety as it offers interior mutability but it only works for &lt;code&gt;Copy&lt;/code&gt; types and makes mutation less visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  RefCell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html" rel="noopener noreferrer"&gt;RefCell&lt;/a&gt; is pretty similar to &lt;code&gt;Cell&lt;/code&gt; but it does not need the contained value to have the &lt;code&gt;Copy&lt;/code&gt; trait. It can become really dangerous as if you call the &lt;code&gt;borrow_mut&lt;/code&gt; function while there is any borrow in place (mutable or immutable), your app will panic. This is one of the few places where Rust enforces borrowing rules at runtime instead of compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  LazyLock
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/sync/struct.LazyLock.html" rel="noopener noreferrer"&gt;LazyLock&lt;/a&gt; is pretty popular for using the singleton-like global initialization in a multi-threaded context. It implements the &lt;code&gt;Sync&lt;/code&gt; trait, being able to be used in statics, making it perfect for database connections, http clients, etc shared across threads. It is lazily initialized, meaning that the initialization code is only executed when the value is first accessed. The only downside is that the initialization code must be synchronous. &lt;code&gt;Lazy&lt;/code&gt; smart pointers must have the initialization logic upfront and the closure must be known at compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  LazyCell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/cell/struct.LazyCell.html" rel="noopener noreferrer"&gt;LazyCell&lt;/a&gt; is similar to &lt;code&gt;LazyLock&lt;/code&gt; but without locking and without implementing the &lt;code&gt;Sync&lt;/code&gt; trait. As &lt;code&gt;LazyLock&lt;/code&gt;, it is lazily initialized. I haven't found a use case for my projects yet, as I always lean towards &lt;code&gt;LazyLock&lt;/code&gt; or &lt;code&gt;OnceLock&lt;/code&gt;. Only good for single-threaded contexts.&lt;/p&gt;

&lt;h2&gt;
  
  
  OnceLock
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/sync/struct.OnceLock.html" rel="noopener noreferrer"&gt;OnceLock&lt;/a&gt; fixes the &lt;code&gt;LazyLock&lt;/code&gt; async problem by not requiring a closure to initialize and allows you to set the value later, even after performing an async operation. &lt;code&gt;Once&lt;/code&gt; smart pointers can be initialized with different logic across your app depending on the context but can only be initialized once and stored by using the &lt;code&gt;set&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  OnceCell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/cell/struct.OnceCell.html" rel="noopener noreferrer"&gt;OnceCell&lt;/a&gt; is another &lt;code&gt;Once&lt;/code&gt; smart pointer, similar to &lt;code&gt;LazyCell&lt;/code&gt; (not thread-safe) but being able to be initialized with different logic across your app. &lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy vs Once, a quick comparison
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Lazy vs Once&lt;/span&gt;
&lt;span class="c1"&gt;// Lazy&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;STRIPE_CLIENT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LazyLock&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;LazyLock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// LazyLock panics if initialization panics&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nn"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Once&lt;/span&gt;
&lt;span class="c1"&gt;// Can be set from anywhere, even async contexts&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;DB_POOL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OnceLock&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OnceLock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PgPool&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postgres_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DB_POOL&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/borrow/enum.Cow.html" rel="noopener noreferrer"&gt;Cow&lt;/a&gt; implements clone on write functionality, it is used in scenarios where you have to work with a shared reference to some existing data or creating a new variable and maintain ownership of it. &lt;code&gt;Rc::make_mut&lt;/code&gt; and &lt;code&gt;Arc::make_mut&lt;/code&gt; also have clone on write semantics but keep a reference count. &lt;code&gt;Cow&lt;/code&gt; can be useful when you want to avoid unnecessary cloning of data just for reading. An example is better than a hundred words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;process_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Cow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Cow&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ERROR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// As it needs to be modified, cow clones here&lt;/span&gt;
        &lt;span class="nn"&gt;Cow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Owned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"WARNING"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// No modification needed - just return the borrowed data with no clones&lt;/span&gt;
        &lt;span class="n"&gt;input&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/pin/struct.Pin.html" rel="noopener noreferrer"&gt;Pin&lt;/a&gt; ensures the memory location for the data stored never changes. It works well to store async functions that you don't want to call &lt;code&gt;await&lt;/code&gt; at the same moment they are declared. This is required when some futures are self-referential as moving a future after it has been polled can invalidate internal pointers and result in undefined behavior. Use pin in a situation like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Pin&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Bye world!"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Now we can call await on all the pinned futures&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;future&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;join_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Weak
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/rc/struct.Weak.html" rel="noopener noreferrer"&gt;Weak&lt;/a&gt; is not really popular as the reference-count alternatives, it keeps a weak reference count but does not keep the data alive. Once all strong references are dropped, the data is deallocated and any remaining &lt;code&gt;Weak&lt;/code&gt; pointers will fail to be accessed. It is only useful when you want to read data but it may or may not be there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;And that's it! That was a quick tour of one of the most important concepts in Rust - smart pointers. I find them incredibly useful for managing memory and ensuring data integrity in concurrent environments but they can be dangerous if you don't choose the right one for the right job.&lt;/p&gt;

&lt;p&gt;Personally, I tend to lean towards &lt;code&gt;RwLock&lt;/code&gt;, &lt;code&gt;Rc&lt;/code&gt; and &lt;code&gt;Arc&lt;/code&gt; for most cases. However, all of them can be useful in different scenarios, so it's good to know their strengths and weaknesses.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>smartpointers</category>
    </item>
    <item>
      <title>How to deploy a simple Axum app to a VPS using Kamal</title>
      <dc:creator>Marc Cámara</dc:creator>
      <pubDate>Wed, 14 Jan 2026 12:45:00 +0000</pubDate>
      <link>https://dev.to/mcamara/how-to-deploy-a-simple-axum-app-to-a-vps-using-kamal-1gno</link>
      <guid>https://dev.to/mcamara/how-to-deploy-a-simple-axum-app-to-a-vps-using-kamal-1gno</guid>
      <description>&lt;p&gt;When we first deploy a small or medium-sized &lt;a href="https://github.com/tokio-rs/axum" rel="noopener noreferrer"&gt;Axum&lt;/a&gt; app, the priority is to get it running as fast and as cheaply as possible but starting with a complex infrastructure for a project that is still not live or is not big enough is usually a waste of time and resources.&lt;/p&gt;

&lt;p&gt;Tools or platforms like Kubernetes, AWS, Google Cloud, Terraform... they all have a learning curve and usually come with a high cost.&lt;/p&gt;

&lt;p&gt;In this article, I will show you how to deploy to your own VPS, which is a great option for small or medium-sized projects. It’s cheap, easy to set up, and can be scaled up or down as needed. For this example, we will use &lt;a href="https://www.hetzner.com/" rel="noopener noreferrer"&gt;Hetzner&lt;/a&gt; as our VPS provider, but you can use any VPS provider you like (DigitalOcean, Vultr, Linode...) as long as it supports SSH access.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Kamal?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kamal-deploy.org" rel="noopener noreferrer"&gt;Kamal&lt;/a&gt; is a deployment tool created by &lt;a href="https://x.com/dhh" rel="noopener noreferrer"&gt;DHH&lt;/a&gt;, the creator of &lt;a href="https://rubyonrails.org" rel="noopener noreferrer"&gt;Ruby on Rails&lt;/a&gt;. As stated in their website:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kamal offers zero-downtime deploys, rolling restarts, asset bridging, remote builds, accessory service management, and everything else you need to deploy and manage your web app in production with Docker. Originally built for Rails apps, Kamal will work with any type of web app that can be containerized.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many people dismiss Kamal because it was originally built as a deployment tool for Rails apps. However, when inspected more closely, it’s a powerful tool that can be used for any type of web application that can be containerized. It’s a great option for small or medium-sized projects that need a simple, easy-to-use deployment tool, regardless of the framework or language used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick note from the developer
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;You are looking at one of the articles on my &lt;a href="https://marccamara.com" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt;, please support me by visiting it, thanks!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Before we start, let's talk about the scope we will cover
&lt;/h3&gt;

&lt;p&gt;This is not an article about replacing Kubernetes or Terraform.&lt;/p&gt;

&lt;p&gt;Kamal is not trying to solve the same problems as Kubernetes, and this post is not arguing that you should abandon complex platforms for large or highly distributed systems. Kubernetes, Terraform, and similar tools exist for good reasons and are the right choice in many scenarios.&lt;/p&gt;

&lt;p&gt;This article focuses on a different problem: deploying a small or medium-sized web application in a simple, cost-effective way, without taking on unnecessary operational complexity before it’s actually needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's get started
&lt;/h3&gt;

&lt;p&gt;For this article there will be some assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a Hetzner account and have created a VPS. The cheapest server will work. At the time of writing, the cheapest option is the CX23, which costs less than $5/month and includes 4GB of RAM, 40GB of SSD, and 2 vCPU cores, more than enough for our tests.&lt;/li&gt;
&lt;li&gt;You have Docker installed. By default, Kamal uploads your Docker images to Docker Hub publicly. If you want to change to a different container registry or keep your images private on Docker Hub, you can find a guide &lt;a href="https://kamal-deploy.org/docs/configuration/docker-registry/#using-docker-hub-as-the-container-registry" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You have a bare Axum app ready to deploy (or any other web application that can be containerized). I have an example &lt;a href="https://github.com/mcamara/kamal-axum-example" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The project you want to deploy has a valid Dockerfile. You can see an example &lt;a href="https://github.com/mcamara/kamal-axum-example/blob/main/Dockerfile" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the Axum app, any application will work as long as it exposes a health endpoint. We will use Kamal’s default (&lt;code&gt;"/up"&lt;/code&gt;), but any other endpoint can be used if it’s correctly configured in the &lt;code&gt;kamal.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Let’s start by running the following commands from the root of the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;kamal
kamal init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands create a &lt;code&gt;config/deploy.yml&lt;/code&gt; file and a &lt;code&gt;.kamal/secrets.yml&lt;/code&gt; file with the default configuration (we will ignore hooks for now).&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;.kamal/secrets.yml&lt;/code&gt; file can read secrets from environment variables or a password manager (it works with 1Password by default). For this example, we will use environment variables, but keeping your secrets in a password manager is the recommended approach. We will keep the image private on Docker Hub, so we’ll uncomment the following line in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Option 1: Read secrets from the environment&lt;/span&gt;
&lt;span class="nv"&gt;KAMAL_REGISTRY_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$KAMAL_REGISTRY_PASSWORD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fun starts in the &lt;code&gt;config/deploy.yml&lt;/code&gt; file. Let’s start editing the parts we need for this example.&lt;/p&gt;

&lt;p&gt;First, we need to define the service name, the image name, and the IP of the server we want to deploy to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;axum-post-example&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; The name of your service, just use the same name you have on your Cargo.toml file&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-docker-hub-user/axum-post-example&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; The username on Docker Hub and the name of the image that will be created and stored&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;116.111.111.111&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; The ip of the server created on your VPS platform&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we need to define the URL where the application will be deployed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ssl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.marccamara.com&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; The url where you want your app to be deployed, remember to setup the DNS records&lt;/span&gt;
  &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/up&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; /up is the default endpoint, so no need to add this line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we need to define where the newly created image will live, along with the password (if you want your images to be private):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-docker-hub-user&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;KAMAL_REGISTRY_PASSWORD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all!&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying
&lt;/h3&gt;

&lt;p&gt;Now that everything is ready, we can do our first deployment by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kamal setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the deployment to finish, then check if everything is working by visiting &lt;code&gt;https://your-website.com/up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Subsequent deployments can be done by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kamal deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may have noticed, Kamal has handled the SSL certificate and proxy configuration for us, which is pretty cool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finishing up
&lt;/h3&gt;

&lt;p&gt;We’ve successfully deployed our application. While this setup looks simple, Kamal can do much more: it can deploy databases, deploy to multiple servers, perform zero-downtime deploys, and support multiple environments (for example, by adding a &lt;code&gt;.config/deploy.staging.yml&lt;/code&gt; file), among other things.&lt;/p&gt;

&lt;p&gt;I’m currently using Kamal for two different projects: one medium-sized setup with Postgres, Valkey and two servers in different locations, and this very personal page running on Leptos with caching.&lt;/p&gt;

&lt;p&gt;I may talk about these setups in a future post, but for now, I hope you enjoyed this article and learned something new.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
