diff --git a/src/timeline/TimelineView.cpp b/src/timeline/TimelineView.cpp
index 61a507b392066859cbf640ca0641466416aeb504..95cde0f4ed4c1719fd1949099681d299c7069d2b 100644
--- a/src/timeline/TimelineView.cpp
+++ b/src/timeline/TimelineView.cpp
@@ -38,6 +38,10 @@
 
 using TimelineEvent = mtx::events::collections::TimelineEvents;
 
+//! Maximum number of widgets to keep in the timeline layout.
+constexpr int MAX_RETAINED_WIDGETS = 100;
+constexpr int MIN_SCROLLBAR_HANDLE = 60;
+
 //! Retrieve the timestamp of the event represented by the given widget.
 QDateTime
 getDate(QWidget *widget)
@@ -481,8 +485,7 @@ TimelineView::addEvents(const mtx::responses::Timeline &timeline)
 void
 TimelineView::init()
 {
-        QSettings settings;
-        local_user_ = settings.value("auth/user_id").toString();
+        local_user_ = utils::localUser();
 
         QIcon icon;
         icon.addFile(":/icons/icons/ui/angle-arrow-down.png");
@@ -965,6 +968,19 @@ TimelineView::showEvent(QShowEvent *event)
         QWidget::showEvent(event);
 }
 
+void
+TimelineView::hideEvent(QHideEvent *event)
+{
+        const auto handleHeight = scroll_area_->verticalScrollBar()->sizeHint().height();
+        const auto widgetsNum   = scroll_layout_->count();
+
+        // Remove widgets from the timeline to reduce the memory footprint.
+        if (handleHeight < MIN_SCROLLBAR_HANDLE && widgetsNum > MAX_RETAINED_WIDGETS)
+                clearTimeline();
+
+        QWidget::hideEvent(event);
+}
+
 bool
 TimelineView::event(QEvent *event)
 {
@@ -974,6 +990,30 @@ TimelineView::event(QEvent *event)
         return QWidget::event(event);
 }
 
+void
+TimelineView::clearTimeline()
+{
+        // Delete all widgets.
+        QLayoutItem *item;
+        while ((item = scroll_layout_->takeAt(0)) != nullptr) {
+                delete item->widget();
+                delete item;
+        }
+
+        // The next call to /messages will be without a prev token.
+        prev_batch_token_.clear();
+        eventIds_.clear();
+
+        // Clear queues with pending messages to be rendered.
+        bottomMessages_.clear();
+        topMessages_.clear();
+
+        firstSender_.clear();
+        lastSender_.clear();
+
+        scroll_layout_->addStretch(1);
+}
+
 void
 TimelineView::toggleScrollDownButton()
 {
diff --git a/src/timeline/TimelineView.h b/src/timeline/TimelineView.h
index 5c42415a3be20416b731ad7a212120c9c6003826..d622b698839618554a823159c9d813aa8ec7dc73 100644
--- a/src/timeline/TimelineView.h
+++ b/src/timeline/TimelineView.h
@@ -161,6 +161,7 @@ signals:
 protected:
         void paintEvent(QPaintEvent *event) override;
         void showEvent(QShowEvent *event) override;
+        void hideEvent(QHideEvent *event) override;
         bool event(QEvent *event) override;
 
 private:
@@ -271,6 +272,8 @@ private:
 
         //! Store the event id associated with the given widget.
         void saveEventId(QWidget *widget);
+        //! Remove all widgets from the timeline layout.
+        void clearTimeline();
 
         QVBoxLayout *top_layout_;
         QVBoxLayout *scroll_layout_;