diff --git a/crates/core/src/database/channels.rs b/crates/core/src/database/channels.rs
index ed28323..b3dc31b 100644
--- a/crates/core/src/database/channels.rs
+++ b/crates/core/src/database/channels.rs
@@ -21,6 +21,7 @@ impl DataManager {
             position: get!(x->6(i32)) as usize,
             members: serde_json::from_str(&get!(x->7(String))).unwrap(),
             title: get!(x->8(String)),
+            last_message: get!(x->9(i64)) as usize,
         }
     }
 
@@ -81,7 +82,7 @@ impl DataManager {
 
         let res = query_rows!(
             &conn,
-            "SELECT * FROM channels WHERE (owner = $1 OR members LIKE $2) AND community = 0 ORDER BY created DESC",
+            "SELECT * FROM channels WHERE (owner = $1 OR members LIKE $2) AND community = 0 ORDER BY last_message DESC",
             params![&(user as i64), &format!("%{user}%")],
             |x| { Self::get_channel_from_row(x) }
         );
@@ -162,7 +163,7 @@ impl DataManager {
 
         let res = execute!(
             &conn,
-            "INSERT INTO channels VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
+            "INSERT INTO channels VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
             params![
                 &(data.id as i64),
                 &(data.community as i64),
@@ -172,7 +173,8 @@ impl DataManager {
                 &(data.minimum_role_write as i32),
                 &(data.position as i32),
                 &serde_json::to_string(&data.members).unwrap(),
-                &data.title
+                &data.title,
+                &(data.last_message as i64)
             ]
         );
 
@@ -320,4 +322,5 @@ impl DataManager {
     auto_method!(update_channel_minimum_role_read(i32)@get_channel_by_id:MANAGE_CHANNELS -> "UPDATE channels SET minimum_role_read = $1 WHERE id = $2" --cache-key-tmpl="atto.channel:{}");
     auto_method!(update_channel_minimum_role_write(i32)@get_channel_by_id:MANAGE_CHANNELS -> "UPDATE channels SET minimum_role_write = $1 WHERE id = $2" --cache-key-tmpl="atto.channel:{}");
     auto_method!(update_channel_members(Vec<usize>)@get_channel_by_id:MANAGE_CHANNELS -> "UPDATE channels SET members = $1 WHERE id = $2" --serde --cache-key-tmpl="atto.channel:{}");
+    auto_method!(update_channel_last_message(i64) -> "UPDATE channels SET last_message = $1 WHERE id = $2" --cache-key-tmpl="atto.channel:{}");
 }
diff --git a/crates/core/src/database/common.rs b/crates/core/src/database/common.rs
index 8536b88..7e7a7f6 100644
--- a/crates/core/src/database/common.rs
+++ b/crates/core/src/database/common.rs
@@ -164,7 +164,15 @@ macro_rules! auto_method {
                 .get(format!($cache_key_tmpl, selector.to_string()))
                 .await
             {
-                return Ok(serde_json::from_str(&cached).unwrap());
+                match serde_json::from_str(&cached) {
+                    Ok(x) => return Ok(x),
+                    Err(_) => {
+                        self.0
+                            .1
+                            .remove(format!($cache_key_tmpl, selector.to_string()))
+                            .await
+                    }
+                };
             }
 
             let conn = match self.0.connect().await {
diff --git a/crates/core/src/database/drivers/sql/create_channels.sql b/crates/core/src/database/drivers/sql/create_channels.sql
index 6b8a29b..83f7ff6 100644
--- a/crates/core/src/database/drivers/sql/create_channels.sql
+++ b/crates/core/src/database/drivers/sql/create_channels.sql
@@ -7,5 +7,6 @@ CREATE TABLE IF NOT EXISTS channels (
     minimum_role_write INT NOT NULL,
     position INT NOT NULL,
     members TEXT NOT NULL,
-    title TEXT NOT NULL
+    title TEXT NOT NULL,
+    last_message BIGINT NOT NULL
 )
diff --git a/crates/core/src/database/messages.rs b/crates/core/src/database/messages.rs
index f5c7024..6c60cd7 100644
--- a/crates/core/src/database/messages.rs
+++ b/crates/core/src/database/messages.rs
@@ -254,6 +254,10 @@ impl DataManager {
             return Err(Error::MiscError(e.to_string()));
         }
 
+        // update channel position
+        self.update_channel_last_message(channel.id, unix_epoch_timestamp() as i64)
+            .await?;
+
         // ...
         Ok(())
     }
diff --git a/crates/core/src/model/channels.rs b/crates/core/src/model/channels.rs
index 5b95d2e..b7023d3 100644
--- a/crates/core/src/model/channels.rs
+++ b/crates/core/src/model/channels.rs
@@ -24,21 +24,26 @@ pub struct Channel {
     pub members: Vec<usize>,
     /// The title of the channel.
     pub title: String,
+    /// The timestamp of the last message in the channel.
+    pub last_message: usize,
 }
 
 impl Channel {
     /// Create a new [`Channel`].
     pub fn new(community: usize, owner: usize, position: usize, title: String) -> Self {
+        let created = unix_epoch_timestamp();
+
         Self {
             id: Snowflake::new().to_string().parse::<usize>().unwrap(),
             community,
             owner,
-            created: unix_epoch_timestamp(),
+            created,
             minimum_role_read: (CommunityPermission::DEFAULT | CommunityPermission::MEMBER).bits(),
             minimum_role_write: (CommunityPermission::DEFAULT | CommunityPermission::MEMBER).bits(),
             position,
             members: Vec::new(),
             title,
+            last_message: created,
         }
     }
 
diff --git a/sql_changes/channels_last_message.sql b/sql_changes/channels_last_message.sql
new file mode 100644
index 0000000..9709200
--- /dev/null
+++ b/sql_changes/channels_last_message.sql
@@ -0,0 +1,2 @@
+ALTER TABLE channels
+ADD COLUMN last_message BIGINT NOT NULL DEFAULT '0';