diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt
index dd8b2b764d6b1423b8f822096f9eae334da51b37..a0134e299cfa660c5ec3fd87a670635fff0868a1 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt
@@ -13,10 +13,8 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage {
       for ((bufferId, bufferMessages) in messages.sortedBy { it.messageId }.groupBy { it.bufferInfo.bufferId }) {
         val lastMessageId = db.message().findLastByBufferId(bufferId)?.messageId
         val firstMessage = bufferMessages.firstOrNull()
-        if (lastMessageId != null && firstMessage != null) {
-          if (lastMessageId < firstMessage.messageId) {
-            db.message().clearMessages(bufferId)
-          }
+        if (lastMessageId == null || firstMessage == null || lastMessageId < firstMessage.messageId) {
+          db.message().clearMessages(bufferId)
         }
       }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt
index 88942631b463280ec16b7c9559d8e0cb0a591787..4c618ac3304f0bacb62b547f2f825a92bdd12de4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt
@@ -211,6 +211,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
     )
     chatList.layoutManager = LinearLayoutManager(context)
     chatList.itemAnimator = DefaultItemAnimator()
+    chatList.setItemViewCacheSize(10)
     return view
   }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt
index 85428e267a8e4e7cdf785376afe721a18fdf8d1d..bd40477de6a564e9e8556a35d19a5bd20db96e93 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt
@@ -68,5 +68,9 @@ class MessageAdapter(context: Context) :
     messageRenderer.init(viewHolder, messageType, hasHighlight)
     return viewHolder
   }
+
+  operator fun get(position: Int): QuasselDatabase.DatabaseMessage? {
+    return getItem(position)
+  }
 }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt
index a71fe90001dc00f04b79a06e908179f19ec862e4..2b54f1f05b32d45948a370236cc9f3cb22273009 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt
@@ -15,18 +15,20 @@ import android.view.ViewGroup
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.session.Backend
+import de.kuschku.libquassel.session.SessionManager
 import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
 import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
-import de.kuschku.quasseldroid_ng.util.helper.invoke
-import de.kuschku.quasseldroid_ng.util.helper.switchMap
-import de.kuschku.quasseldroid_ng.util.helper.toggle
+import de.kuschku.quasseldroid_ng.util.helper.*
 import de.kuschku.quasseldroid_ng.util.service.ServiceBoundFragment
 
 class MessageListFragment : ServiceBoundFragment() {
   val currentBuffer: MutableLiveData<LiveData<BufferId?>?> = MutableLiveData()
   private val buffer = currentBuffer.switchMap { it }
 
+  private val sessionManager: LiveData<SessionManager?> = backend.map(Backend::sessionManager)
+
   private val handler = AndroidHandlerThread("Chat")
 
   private lateinit var database: QuasselDatabase
@@ -64,6 +66,7 @@ class MessageListFragment : ServiceBoundFragment() {
     val linearLayoutManager = LinearLayoutManager(context)
     linearLayoutManager.reverseLayout = true
     messageList.layoutManager = linearLayoutManager
+    messageList.setItemViewCacheSize(20)
 
     messageList.addOnScrollListener(
       object : RecyclerView.OnScrollListener() {
@@ -85,6 +88,20 @@ class MessageListFragment : ServiceBoundFragment() {
         .build()
     }
 
+    sessionManager.zip(buffer).zip(data).observe(
+      this, Observer {
+      handler.post {
+        val session = it?.first?.first
+        val buffer = it?.first?.second
+        val bufferSyncer = session?.bufferSyncer
+
+        if (buffer != null && bufferSyncer != null) {
+          bufferSyncer.requestMarkBufferAsRead(buffer)
+        }
+      }
+    }
+    )
+
     data.observe(
       this, Observer { list ->
       val findFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition()
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt
index 7071e9bd2b50c62c22d7863de2ca70114302171f..97b627e791ffc3e933e37af7d78fc8e236311e76 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt
@@ -5,7 +5,7 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler
 
 object AndroidLoggingHandler : LoggingHandler() {
   override fun isLoggable(logLevel: LogLevel, tag: String): Boolean {
-    return true || Log.isLoggable(tag, priority(logLevel))
+    return Log.isLoggable(tag, priority(logLevel))
   }
 
   override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
index dad9082c4d25f497d1f6241765accca9baf44937..bf240b73564a686eb8746e8b526d5a77ad131e35 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
@@ -1,6 +1,7 @@
 package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.protocol.Quassel_Features
+import de.kuschku.libquassel.util.helpers.hexDump
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import java.nio.ByteBuffer
 import java.nio.CharBuffer
@@ -46,58 +47,78 @@ abstract class StringSerializer(
   }
 
   override fun serialize(buffer: ChainedByteBuffer, data: String?, features: Quassel_Features) {
-    if (data == null) {
-      IntSerializer.serialize(buffer, -1, features)
-    } else {
-      val charBuffer = charBuffer(data.length)
-      charBuffer.put(data)
-      charBuffer.flip()
-      val byteBuffer = encoder.encode(charBuffer)
-      IntSerializer.serialize(buffer, byteBuffer.remaining() + trailingNullBytes, features)
-      buffer.put(byteBuffer)
-      for (i in 0 until trailingNullBytes)
-        buffer.put(0)
+    try {
+      if (data == null) {
+        IntSerializer.serialize(buffer, -1, features)
+      } else {
+        val charBuffer = charBuffer(data.length)
+        charBuffer.put(data)
+        charBuffer.flip()
+        val byteBuffer = encoder.encode(charBuffer)
+        IntSerializer.serialize(buffer, byteBuffer.remaining() + trailingNullBytes, features)
+        buffer.put(byteBuffer)
+        for (i in 0 until trailingNullBytes)
+          buffer.put(0)
+      }
+    } catch (e: Throwable) {
+      throw RuntimeException(data, e)
     }
   }
 
-  fun serialize(data: String?): ByteBuffer = if (data == null) {
-    ByteBuffer.allocate(0)
-  } else {
-    val charBuffer = charBuffer(data.length)
-    charBuffer.put(data)
-    charBuffer.flip()
-    encoder.encode(charBuffer)
+  fun serialize(data: String?): ByteBuffer {
+    try {
+      if (data == null) {
+        return ByteBuffer.allocate(0)
+      } else {
+        val charBuffer = charBuffer(data.length)
+        charBuffer.put(data)
+        charBuffer.flip()
+        return encoder.encode(charBuffer)
+      }
+    } catch (e: Throwable) {
+      throw RuntimeException(data, e)
+    }
   }
 
   fun deserializeAll(buffer: ByteBuffer): String? {
-    val len = buffer.remaining()
-    return if (len == -1) {
-      null
-    } else {
-      val limit = buffer.limit()
-      buffer.limit(buffer.position() + len - trailingNullBytes)
-      val charBuffer = charBuffer(len)
-      decoder.decode(buffer, charBuffer, true)
-      buffer.limit(limit)
-      buffer.position(buffer.position() + trailingNullBytes)
-      charBuffer.flip()
-      charBuffer.toString()
+    try {
+      val len = buffer.remaining()
+      return if (len == -1) {
+        null
+      } else {
+        val limit = buffer.limit()
+        buffer.limit(buffer.position() + len - trailingNullBytes)
+        val charBuffer = charBuffer(len)
+        decoder.decode(buffer, charBuffer, true)
+        buffer.limit(limit)
+        buffer.position(buffer.position() + trailingNullBytes)
+        charBuffer.flip()
+        charBuffer.toString()
+      }
+    } catch (e: Throwable) {
+      buffer.hexDump()
+      throw RuntimeException(e)
     }
   }
 
   override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): String? {
-    val len = IntSerializer.deserialize(buffer, features)
-    return if (len == -1) {
-      null
-    } else {
-      val limit = buffer.limit()
-      buffer.limit(buffer.position() + Math.max(0, len - trailingNullBytes))
-      val charBuffer = charBuffer(len)
-      decoder.decode(buffer, charBuffer, true)
-      buffer.limit(limit)
-      buffer.position(buffer.position() + trailingNullBytes)
-      charBuffer.flip()
-      charBuffer.toString()
+    try {
+      val len = IntSerializer.deserialize(buffer, features)
+      return if (len == -1) {
+        null
+      } else {
+        val limit = buffer.limit()
+        buffer.limit(buffer.position() + Math.max(0, len - trailingNullBytes))
+        val charBuffer = charBuffer(len)
+        decoder.decode(buffer, charBuffer, true)
+        buffer.limit(limit)
+        buffer.position(buffer.position() + trailingNullBytes)
+        charBuffer.flip()
+        charBuffer.toString()
+      }
+    } catch (e: Throwable) {
+      buffer.hexDump()
+      throw RuntimeException(e)
     }
   }
 }