diff --git a/app/lib/database/helpers/messages.js b/app/lib/database/helpers/messages.js
new file mode 100644
index 0000000000000000000000000000000000000000..b8e4d82885c7bdc7e2351d83c55401711240cae2
--- /dev/null
+++ b/app/lib/database/helpers/messages.js
@@ -0,0 +1,46 @@
+import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
+import buildMessage from '../../methods/helpers/buildMessage';
+
+export const createMessage = (db, message) => {
+	db.action(async(action) => {
+		const messagesCollection = db.collections.get('messages');
+		message = buildMessage(message);
+		console.log('TCL: createMessage -> message', message);
+		let messageRecord;
+		try {
+			messageRecord = await messagesCollection.find(message.id);
+			await messageRecord.update((m) => {
+				m._raw = sanitizedRaw({
+					...m._raw,
+					...message
+				}, messagesCollection.schema);
+				m.ts = message.ts;
+			});
+			// await action.subAction(() => messageRecord.deleteRoles());
+		} catch (error) {
+			messageRecord = await messagesCollection.create((m) => {
+				m._raw = sanitizedRaw({
+					...message
+				}, messagesCollection.schema);
+				m.ts = message.ts;
+			});
+		}
+
+		// if (subscription.roles) {
+		// 	subscription.roles.forEach(async(role) => {
+		// 		try {
+		// 			await action.subAction(() => subscriptionRecord.addRole(role));
+		// 		} catch (error) {
+		// 			console.log('Error creating subscriptionRole -> error', error);
+		// 		}
+		// 	});
+		// }
+	});
+};
+
+export const getUpdatedSince = async(db) => {
+	const subscriptionsCollection = db.collections.get('subscriptions');
+	const subscriptions = await subscriptionsCollection.query().fetch();
+	const sorted = subscriptions.sort((a, b) => a.roomUpdatedAt < b.roomUpdatedAt);
+	return sorted[0] && sorted[0].roomUpdatedAt && sorted[0].roomUpdatedAt.toISOString();
+};
diff --git a/app/lib/database/index.js b/app/lib/database/index.js
index 52f3f7309b39b1cf94ecd25c147815e00ff95422..c661cc49b9f3de7e145cb9da8268ea99a8652f6b 100644
--- a/app/lib/database/index.js
+++ b/app/lib/database/index.js
@@ -11,7 +11,8 @@ import {
 	CustomEmoji,
 	CustomEmojiAlias,
 	Subscription,
-	SubscriptionRole
+	SubscriptionRole,
+	Message
 } from './models';
 
 const serverAdapter = new SQLiteAdapter({
@@ -39,7 +40,8 @@ export const appDatabase = new Database({
 		CustomEmoji,
 		CustomEmojiAlias,
 		Subscription,
-		SubscriptionRole
+		SubscriptionRole,
+		Message
 	]
 });
 
diff --git a/app/lib/database/models/Message.js b/app/lib/database/models/Message.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c088e9c433c37e0b90fe6910f3fc703f07d7e20
--- /dev/null
+++ b/app/lib/database/models/Message.js
@@ -0,0 +1,60 @@
+import { Model, Q } from '@nozbe/watermelondb';
+import { date, field, relation, readonly } from '@nozbe/watermelondb/decorators';
+import lazy from '@nozbe/watermelondb/decorators/lazy';
+import action from '@nozbe/watermelondb/decorators/action';
+
+export default class Message extends Model {
+	static table = 'messages'
+
+	// needs Subscription association or rid query is enough?
+
+	@field('msg') msg
+
+	@field('t') t
+
+	@date('ts') ts
+
+	@field('alias') alias
+
+	@field('groupable') groupable
+
+	@field('avatar') avatar
+
+	@readonly @date('updated_at') updatedAt
+
+	@field('status') status
+
+	@field('pinned') pinned
+
+	@field('starred') starred
+
+	@field('role') role
+
+	@field('rid') rid
+
+	// rid
+	// u
+	// parseUrls????
+	// attachments
+	// urls
+	// editedBy
+	// reactions
+
+	// @lazy
+	// roles = this.collections
+	// 	.get('roles')
+	// 	.query(Q.on('subscriptions_roles', 'subscription_id', this.id));
+
+	// @children('subscriptions_roles') subscriptions_roles
+
+	// @action deleteRoles() {
+	// 	this.subscriptions_roles.destroyAllPermanently();
+	// }
+
+	// @action addRole(roleId) {
+	// 	return this.collections.get('subscriptions_roles').create((sr) => {
+	// 		sr.subscriptionId = this.id;
+	// 		sr.roleId = roleId;
+	// 	});
+	// }
+}
\ No newline at end of file
diff --git a/app/lib/database/models/Subscription.js b/app/lib/database/models/Subscription.js
index 3f59137659e71851becd60b6df0e0e6fa215ebf6..6c55e1a3fa79434984e44efc63a0061c6fd0a3ef 100644
--- a/app/lib/database/models/Subscription.js
+++ b/app/lib/database/models/Subscription.js
@@ -77,4 +77,4 @@ export default class Subscription extends Model {
 			sr.roleId = roleId;
 		});
 	}
-}
\ No newline at end of file
+}
diff --git a/app/lib/database/models/index.js b/app/lib/database/models/index.js
index 563d241ecf7ec2bb9bbd0827d54d7209966127a4..7b3e1c532afb0622d01b3378a2c0df2cd2f0a08c 100644
--- a/app/lib/database/models/index.js
+++ b/app/lib/database/models/index.js
@@ -7,6 +7,7 @@ import CustomEmoji from './CustomEmoji';
 import CustomEmojiAlias from './CustomEmojiAlias';
 import Subscription from './Subscription';
 import SubscriptionRole from './SubscriptionRole';
+import Message from './Message';
 
 export {
 	Server,
@@ -17,5 +18,6 @@ export {
 	CustomEmoji,
 	CustomEmojiAlias,
 	Subscription,
-	SubscriptionRole
+	SubscriptionRole,
+	Message
 };
diff --git a/app/lib/database/schemas/app.js b/app/lib/database/schemas/app.js
index 67300d72cb7da15e0b2a919aac0af03ce0cda01a..8ae2be7eb3d61b45a6fb834dd384d8bd81a692f0 100755
--- a/app/lib/database/schemas/app.js
+++ b/app/lib/database/schemas/app.js
@@ -1,7 +1,7 @@
 import { appSchema, tableSchema } from '@nozbe/watermelondb';
 
 export default appSchema({
-	version: 11,
+	version: 14,
 	tables: [
 		tableSchema({
 			name: 'settings',
@@ -84,6 +84,24 @@ export default appSchema({
 				{ name: 'subscription_id', type: 'string', isIndexed: true },
 				{ name: 'role_id', type: 'string', isIndexed: true }
 			]
+		}),
+		tableSchema({
+			name: 'messages',
+			columns: [
+				{ name: 'msg', type: 'string', isOptional: true },
+				{ name: 't', type: 'string', isOptional: true },
+				// { name: 'subscription_id', type: 'string', isIndexed: true },
+				{ name: 'rid', type: 'string', isIndexed: true },
+				{ name: 'ts', type: 'number' },
+				{ name: 'alias', type: 'string', isOptional: true },
+				{ name: 'groupable', type: 'boolean', isOptional: true },
+				{ name: 'avatar', type: 'string', isOptional: true },
+				{ name: 'updated_at', type: 'number' },
+				{ name: 'status', type: 'number', isOptional: true },
+				{ name: 'pinned', type: 'boolean', isOptional: true },
+				{ name: 'starred', type: 'boolean', isOptional: true },
+				{ name: 'role', type: 'string', isOptional: true }
+			]
 		})
 	]
 });
diff --git a/app/lib/methods/helpers/normalizeMessage.js b/app/lib/methods/helpers/normalizeMessage.js
index 7b77c9ad8f56d24501e03eeae71e34c7e0b412ac..31e73587e995c130d68a830b4bd7411e8c7a92b2 100644
--- a/app/lib/methods/helpers/normalizeMessage.js
+++ b/app/lib/methods/helpers/normalizeMessage.js
@@ -20,6 +20,7 @@ function normalizeAttachments(msg) {
 export default (msg) => {
 	if (!msg) { return; }
 	msg = normalizeAttachments(msg);
+	msg.id = msg._id || msg.id;
 	msg.reactions = msg.reactions || [];
 	// TODO: api problems
 	// if (Array.isArray(msg.reactions)) {
@@ -31,9 +32,9 @@ export default (msg) => {
 		msg.reactions = Object.keys(msg.reactions).map(key => ({ _id: `${ msg._id }${ key }`, emoji: key, usernames: msg.reactions[key].usernames.map(username => ({ value: username })) }));
 	}
 	msg.urls = msg.urls ? parseUrls(msg.urls) : [];
-	msg._updatedAt = new Date();
+	// msg._updatedAt = new Date();
 	// loadHistory returns msg.starred as object
 	// stream-room-msgs returns msg.starred as an array
-	msg.starred = msg.starred && (Array.isArray(msg.starred) ? msg.starred.length > 0 : !!msg.starred);
+	msg.starred = (msg.starred && (Array.isArray(msg.starred) ? msg.starred.length > 0 : !!msg.starred)) || false;
 	return msg;
 };
diff --git a/app/lib/methods/loadMessagesForRoom.js b/app/lib/methods/loadMessagesForRoom.js
index 49d231746c164c69fb7799fae768c039a77921ab..c9f63528fcd753f5d139a811c5b381d700f90d6d 100644
--- a/app/lib/methods/loadMessagesForRoom.js
+++ b/app/lib/methods/loadMessagesForRoom.js
@@ -3,6 +3,8 @@ import { InteractionManager } from 'react-native';
 import buildMessage from './helpers/buildMessage';
 import database from '../realm';
 import log from '../../utils/log';
+import { createMessage } from '../database/helpers/messages';
+import { appDatabase } from '../database';
 
 async function load({ rid: roomId, latest, t }) {
 	if (t === 'l') {
@@ -20,9 +22,9 @@ async function load({ rid: roomId, latest, t }) {
 	}
 
 	let params = { roomId, count: 50 };
-	if (latest) {
-		params = { ...params, latest: new Date(latest).toISOString() };
-	}
+	// if (latest) {
+	// 	params = { ...params, latest: new Date(latest).toISOString() };
+	// }
 	// RC 0.48.0
 	const data = await this.sdk.get(`${ this.roomTypeToApiType(t) }.history`, params);
 	if (!data || data.status === 'error') {
@@ -37,14 +39,20 @@ export default function loadMessagesForRoom(...args) {
 			const data = await load.call(this, ...args);
 
 			if (data && data.length) {
-				InteractionManager.runAfterInteractions(() => {
-					database.write(() => data.forEach((message) => {
-						database.create('messages', buildMessage(message), true);
-					}));
-					return resolve(data);
+				InteractionManager.runAfterInteractions(async() => {
+					// database.write(() => data.forEach((message) => {
+					// 	database.create('messages', buildMessage(message), true);
+					// }));
+					// const messagesCollection = appDatabase.collections.get('messages');
+					// await messagesCollection.query().destroyAllPermanently();
+					const dbActions = [];
+					data.forEach((message) => {
+						dbActions.push(createMessage(appDatabase, message));
+					});
+					await Promise.all(dbActions);
 				});
 			} else {
-				return resolve([]);
+				return resolve();
 			}
 		} catch (e) {
 			log('loadMessagesForRoom', e);