diff --git a/Sources/Database/DB+Contact.swift b/Sources/Database/DB+Contact.swift
deleted file mode 100644
index 4207fea75d83ea0ef6e56ae361cb5a172c8773c7..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+Contact.swift
+++ /dev/null
@@ -1,57 +0,0 @@
-import GRDB
-import Models
-
-extension Contact: Persistable {    
-    public enum Column: String, ColumnExpression {
-        case id
-        case photo
-        case email
-        case phone
-        case userId
-        case status
-        case username
-        case isRecent
-        case nickname
-        case marshaled
-        case createdAt
-    }
-
-    public mutating func didInsert(with rowID: Int64, for column: String?) {
-        id = rowID
-    }
-    
-    public static func query(_ request: Request) -> QueryInterfaceRequest<Contact> {
-        switch request {
-        case .all:
-            return Contact.all()
-        case .isRecent:
-            return Contact
-                .filter(Column.isRecent == true)
-                .order(Column.createdAt.desc)
-        case .verificationInProgress:
-            return Contact.filter(Column.status == Contact.Status.verificationInProgress.rawValue)
-        case .failed:
-            return Contact.filter(
-                Column.status == Contact.Status.requestFailed.rawValue ||
-                Column.status == Contact.Status.confirmationFailed.rawValue
-            )
-        case .requested:
-            return Contact.filter(
-                Column.status == Contact.Status.requested.rawValue ||
-                Column.status == Contact.Status.requesting.rawValue
-            )
-        case .received:
-            return Contact.filter(
-                Column.status == Contact.Status.hidden.rawValue ||
-                Column.status == Contact.Status.verified.rawValue ||
-                Column.status == Contact.Status.verificationFailed.rawValue ||
-                Column.status == Contact.Status.verificationInProgress.rawValue
-            )
-
-        case .friends: return Contact.filter(Column.status == Contact.Status.friend.rawValue)
-        case let .withUserId(data): return Contact.filter(Column.userId == data)
-        case let .withUserIds(ids): return Contact.filter(ids.contains(Contact.Column.userId))
-        case let .withUsername(username): return Contact.filter(Column.username.like("\(username)%"))
-        }
-    }
-}
diff --git a/Sources/Database/DB+FileTransfer.swift b/Sources/Database/DB+FileTransfer.swift
deleted file mode 100644
index 617d8ce34c0b60f3a54c4e9f18e68cfa0ba1dc67..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+FileTransfer.swift
+++ /dev/null
@@ -1,26 +0,0 @@
-import GRDB
-import Models
-
-extension FileTransfer: Persistable {
-    public enum Column: String, ColumnExpression {
-        case id
-        case tid
-        case contact
-        case fileName
-        case fileType
-        case isIncoming
-    }
-
-    public mutating func didInsert(with rowID: Int64, for column: String?) {
-        id = rowID
-    }
-
-    public static func query(_ request: Request) -> QueryInterfaceRequest<FileTransfer> {
-        switch request {
-        case .withTID(let transferId):
-            return FileTransfer.filter(Column.tid == transferId)
-        case .withContactId(let contactId):
-            return FileTransfer.filter(Column.contact == contactId)
-        }
-    }
-}
diff --git a/Sources/Database/DB+Group.swift b/Sources/Database/DB+Group.swift
deleted file mode 100644
index dc78a33efae1c30fd484d7fd2c99e3e996134ec2..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+Group.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-import GRDB
-import Models
-
-extension Group: Persistable {
-    static let members = hasMany(GroupMember.self)
-
-    public enum Column: String, ColumnExpression {
-        case id
-        case name
-        case leader
-        case groupId
-        case status
-        case serialize
-        case createdAt
-        case accepted // Deprecated
-    }
-
-    public mutating func didInsert(with rowID: Int64, for column: String?) {
-        id = rowID
-    }
-
-    public static func query(_ request: Request) -> QueryInterfaceRequest<Group> {
-        switch request {
-        case .withGroupId(let id):
-            return Group.filter(Column.groupId == id)
-        case .accepted:
-            return Group.filter(Column.status == Group.Status.participating.rawValue)
-        case .pending:
-            return Group.filter(
-                Column.status == Group.Status.pending.rawValue ||
-                Column.status == Group.Status.hidden.rawValue
-            )
-        }
-    }
-}
diff --git a/Sources/Database/DB+GroupChatInfo.swift b/Sources/Database/DB+GroupChatInfo.swift
deleted file mode 100644
index 4be4dfad3fccda964b68873b5ddcf3cc4253aeed..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+GroupChatInfo.swift
+++ /dev/null
@@ -1,38 +0,0 @@
-import GRDB
-import Models
-
-extension GroupChatInfo: Requestable  {
-    public static func query(_ request: Request) -> QueryInterfaceRequest<GroupChatInfo> {
-        let lastMessageRequest = GroupMessage
-            .annotated(with: max(GroupMessage.Column.timestamp))
-            .group(GroupMessage.Column.groupId)
-
-        let lastMessageCTE = CommonTableExpression<GroupMessage>(
-            named: "lastMessage",
-            request: lastMessageRequest
-        )
-
-        let lastMessage = Group.association(to: lastMessageCTE) { group, lastMessage in
-            lastMessage[GroupMessage.Column.groupId] == group[Group.Column.groupId]
-        }.order(GroupMessage.Column.timestamp.desc)
-
-        switch request {
-        case .fromGroup(let groupId):
-            return Group
-                .filter(Group.Column.status == Group.Status.participating.rawValue)
-                .filter(Group.Column.groupId == groupId)
-                .with(lastMessageCTE)
-                .including(optional: lastMessage)
-                .including(all: Group.members.forKey("members"))
-                .asRequest(of: Self.self)
-
-        case .accepted:
-            return Group
-                .filter(Group.Column.status == Group.Status.participating.rawValue)
-                .with(lastMessageCTE)
-                .including(optional: lastMessage)
-                .including(all: Group.members.forKey("members"))
-                .asRequest(of: Self.self)
-        }
-    }
-}
diff --git a/Sources/Database/DB+GroupMember.swift b/Sources/Database/DB+GroupMember.swift
deleted file mode 100644
index 2153704e4d14c37b9a4e122ca77299b76bd655a6..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+GroupMember.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-import GRDB
-import Models
-
-extension GroupMember: Persistable {
-    public enum Column: String, ColumnExpression {
-        case id
-        case photo
-        case status
-        case userId
-        case groupId
-        case username
-    }
-
-    public mutating func didInsert(with rowID: Int64, for column: String?) {
-        id = rowID
-    }
-
-    public static func query(_ request: Request) -> QueryInterfaceRequest<GroupMember> {
-        switch request {
-        case .all:
-            return GroupMember.all()
-        case let .withUserId(userId):
-            return GroupMember.filter(Column.userId == userId)
-        case .fromGroup(let groupId):
-            return GroupMember.filter(Column.groupId == groupId)
-        case .strangers:
-            return GroupMember.filter(
-                Column.status == GroupMember.Status.pendingUsername.rawValue
-            )
-        }
-    }
-}
diff --git a/Sources/Database/DB+GroupMessage.swift b/Sources/Database/DB+GroupMessage.swift
deleted file mode 100644
index 7ec6754d6fa0073ba6995b0a44145d1e4a16099e..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+GroupMessage.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-import GRDB
-import Models
-
-extension GroupMessage: Persistable {
-    public enum Column: String, ColumnExpression {
-        case id
-        case sender
-        case status
-        case unread
-        case payload
-        case groupId
-        case uniqueId
-        case roundURL
-        case timestamp
-        case roundId
-    }
-
-    public mutating func didInsert(with rowID: Int64, for column: String?) {
-        id = rowID
-    }
-
-    public static func query(_ request: Request) -> QueryInterfaceRequest<GroupMessage> {
-        switch request {
-        case let .withUniqueId(id):
-            return GroupMessage.filter(Column.uniqueId == id)
-        case let .id(id):
-            return GroupMessage.filter(Column.id == id)
-        case let .fromGroup(id):
-            return GroupMessage.filter(Column.groupId == id).order(Column.timestamp.asc)
-        case let .unreadsFromGroup(id):
-            return GroupMessage.filter(Column.groupId == id).filter(Column.unread == true)
-        case .sending:
-            return GroupMessage.filter(Column.status == GroupMessage.Status.sending.rawValue)
-        }
-    }
-}
diff --git a/Sources/Database/DB+Message.swift b/Sources/Database/DB+Message.swift
deleted file mode 100644
index b5057ea99d870f7861df21f46dac9b47c92d245d..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+Message.swift
+++ /dev/null
@@ -1,46 +0,0 @@
-import GRDB
-import Models
-
-extension Message: Persistable {
-    public enum Column: String, ColumnExpression {
-        case id
-        case report
-        case sender
-        case unread
-        case status
-        case payload
-        case roundURL
-        case receiver
-        case uniqueId
-        case timestamp
-    }
-
-    public mutating func didInsert(with rowID: Int64, for column: String?) {
-        id = rowID
-    }
-
-    public static func query(_ request: Request) -> QueryInterfaceRequest<Message> {
-        switch request {
-        case let .withUniqueId(id):
-            return Message.filter(Column.uniqueId == id)
-        case let .unreadsFromContactId(id):
-            return Message
-                .filter(Column.sender == id || Column.receiver == id)
-                .filter(Column.unread == true)
-
-        case let .latestOnesFromContactIds(ids):
-            return Message
-                .annotated(with: Column.timestamp)
-                .filter(ids.contains(Column.sender) || ids.contains(Column.receiver))
-
-        case let .withId(id):
-            return Message.filter(Column.id == id)
-        case let .withContact(id):
-            return Message.filter(Column.sender == id || Column.receiver == id)
-        case .sending:
-            return Message.filter(Column.status == Message.Status.sending.rawValue)
-        case .sendingAttachment:
-            return Message.filter(Column.status == Message.Status.sendingAttachment.rawValue)
-        }
-    }
-}
diff --git a/Sources/Database/DB+SingleChatInfo.swift b/Sources/Database/DB+SingleChatInfo.swift
deleted file mode 100644
index 16fbc4ff9299a8decc603559c09beebf1aa16f9b..0000000000000000000000000000000000000000
--- a/Sources/Database/DB+SingleChatInfo.swift
+++ /dev/null
@@ -1,27 +0,0 @@
-import GRDB
-import Models
-
-extension SingleChatInfo: Requestable {
-    public static func query(_ request: Request) -> QueryInterfaceRequest<SingleChatInfo> {
-        let lastMessageRequest = Message
-            .annotated(with: max(Message.Column.timestamp))
-            .group(Message.Column.sender || Message.Column.receiver)
-
-        let lastMessageCTE = CommonTableExpression<Message>(
-            named: "lastMessage",
-            request: lastMessageRequest
-        )
-
-        let lastMessage = Contact.association(to: lastMessageCTE) { contact, lastMessage in
-            lastMessage[Message.Column.sender] == contact[Contact.Column.userId] ||
-            lastMessage[Message.Column.receiver] == contact[Contact.Column.userId]
-        }.order(Message.Column.timestamp.desc)
-
-        switch request {
-        case .all:
-            return Contact.with(lastMessageCTE)
-                .including(required: lastMessage)
-                .asRequest(of: Self.self)
-        }
-    }
-}
diff --git a/Sources/Database/DatabaseManager.swift b/Sources/Database/DatabaseManager.swift
deleted file mode 100644
index 86271c2ebfcc146182d867aedf7dd622168807df..0000000000000000000000000000000000000000
--- a/Sources/Database/DatabaseManager.swift
+++ /dev/null
@@ -1,261 +0,0 @@
-import GRDB
-import Models
-import Combine
-import Foundation
-
-public protocol Requestable: FetchableRecord {
-    associatedtype Request
-    static func query(_ request: Request) -> QueryInterfaceRequest<Self>
-}
-
-public protocol Persistable: Requestable & MutablePersistableRecord & Identifiable {
-    var id: Int64? { get }
-}
-
-public protocol DatabaseManager {
-    func drop()
-    func setup() throws
-
-    func updateAll<T>(_ type: T.Type,
-                      _ request: T.Request,
-                      with: [ColumnAssignment]) throws where T: Persistable
-
-    @discardableResult func save<T>(_ model: T) throws -> T where T: Persistable
-    func update<T>(_ model: T) throws where T: Persistable
-    func delete<T>(_ model: T) throws where T: Persistable
-    func fetch<T>(_ request: T.Request) throws -> [T] where T: Requestable
-    func fetch<T>(withId id: Int64) throws -> T? where T: Persistable
-    func publisher<T>(fetch request: T.Request) -> AnyPublisher<[T], Error> where T: Requestable
-    func delete<T>(_ type: T.Type, _ request: T.Request) throws where T: Persistable
-}
-
-public extension DatabaseManager {
-    func publisher<T: Requestable>(
-        fetch type: T.Type,
-        _ request: T.Request
-    ) -> AnyPublisher<[T], Error> {
-        publisher(fetch: request)
-    }
-}
-
-public final class GRDBDatabaseManager {
-    var databaseQueue: DatabaseQueue!
-
-    public init() {}
-}
-
-extension GRDBDatabaseManager: DatabaseManager {
-    public func drop() {
-        try? databaseQueue.write { db in
-            try db.drop(table: Contact.databaseTableName)
-            try db.drop(table: Message.databaseTableName)
-            try db.drop(table: Group.databaseTableName)
-            try db.drop(table: GroupMember.databaseTableName)
-            try db.drop(table: GroupMessage.databaseTableName)
-        }
-    }
-
-    public func updateAll<T>(_ type: T.Type,
-                             _ request: T.Request,
-                             with assignments: [ColumnAssignment]) throws where T : Persistable {
-        _ = try databaseQueue.write {
-            try T.query(request).updateAll($0, assignments)
-        }
-    }
-
-    public func save<T: Persistable>(_ model: T) throws -> T {
-        try databaseQueue.write { db in
-            var model = model
-
-            if model.id == nil {
-                try model.insert(db)
-            } else {
-                try model.update(db)
-            }
-
-            return model
-        }
-    }
-
-    public func update<T>(_ model: T) throws where T: Persistable {
-        try databaseQueue.write { try model.update($0) }
-    }
-
-    public func fetch<T>(withId id: Int64) throws -> T? where T: Persistable {
-        try databaseQueue.read { db in
-            try T.fetchOne(db, key: id)
-        }
-    }
-
-    public func fetch<T>(_ request: T.Request) throws -> [T] where T: Requestable {
-        try databaseQueue.read { db in
-            try T.query(request).fetchAll(db)
-        }
-    }
-
-    public func publisher<T>(fetch request: T.Request) -> AnyPublisher<[T], Error> where T: Requestable {
-        ValueObservation.tracking {
-            try T.query(request).fetchAll($0)
-        }.publisher(in: databaseQueue, scheduling: .immediate)
-        .eraseToAnyPublisher()
-    }
-
-    public func delete<T>(_ model: T) throws where T: Persistable {
-        _ = try databaseQueue.write {
-            try model.delete($0)
-        }
-    }
-
-    public func delete<T>(_ type: T.Type, _ request: T.Request) throws where T: Persistable {
-        _ = try databaseQueue.write {
-            try T.query(request).deleteAll($0)
-        }
-    }
-
-    public func setup() throws {
-        var migrator = DatabaseMigrator()
-
-        let oldPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
-            .appending("/xxmessenger.sqlite")
-
-        let url = FileManager.default
-            .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
-            .appendingPathComponent("database")
-            .appendingPathExtension("sqlite")
-
-        if FileManager.default.fileExists(atPath: oldPath) && !FileManager.default.fileExists(atPath: url.path) {
-            do {
-                try FileManager.default.moveItem(atPath: oldPath, toPath: url.path)
-            } catch {
-                fatalError("Couldn't migrate database from old path to new one: \(error.localizedDescription)")
-            }
-        }
-
-        databaseQueue = try DatabaseQueue(path: url.path)
-        try FileManager.default.setAttributes([
-            .protectionKey : FileProtectionType.completeUntilFirstUserAuthentication
-        ], ofItemAtPath: url.path)
-
-        migrator.registerMigration("v1") { db in
-            try db.create(table: Contact.databaseTableName, ifNotExists: true) { table in
-                table.autoIncrementedPrimaryKey(Contact.Column.id.rawValue, onConflict: .replace)
-                table.column(Contact.Column.photo.rawValue, .blob)
-                table.column(Contact.Column.email.rawValue, .text)
-                table.column(Contact.Column.phone.rawValue, .text)
-                table.column(Contact.Column.nickname.rawValue, .text)
-                table.column(Contact.Column.createdAt.rawValue, .datetime)
-                table.column(Contact.Column.userId.rawValue, .blob).unique()
-                table.column(Contact.Column.username.rawValue, .text).notNull()
-                table.column(Contact.Column.status.rawValue, .integer).notNull()
-                table.column(Contact.Column.marshaled.rawValue, .blob).notNull()
-            }
-
-            try db.create(table: Message.databaseTableName, ifNotExists: true) { table in
-                table.autoIncrementedPrimaryKey(Message.Column.id.rawValue, onConflict: .replace)
-                table.column(Message.Column.report.rawValue, .blob)
-                table.column(Message.Column.uniqueId.rawValue, .blob)
-                table.column(Message.Column.sender.rawValue, .blob).notNull()
-                table.column(Message.Column.payload.rawValue, .text).notNull()
-                table.column(Message.Column.receiver.rawValue, .blob).notNull()
-                table.column(Message.Column.roundURL.rawValue, .text)
-                table.column(Message.Column.status.rawValue, .integer).notNull()
-                table.column(Message.Column.unread.rawValue, .boolean).notNull()
-                table.column(Message.Column.timestamp.rawValue, .integer).notNull()
-            }
-
-            try db.create(table: Group.databaseTableName, ifNotExists: true) { table in
-                table.autoIncrementedPrimaryKey(Group.Column.id.rawValue, onConflict: .replace)
-                table.column(Group.Column.groupId.rawValue, .blob).unique()
-                table.column(Group.Column.name.rawValue, .text).notNull()
-                table.column(Group.Column.leader.rawValue, .blob).notNull()
-                table.column(Group.Column.serialize.rawValue, .blob).notNull()
-                table.column(Group.Column.accepted.rawValue, .boolean).notNull()
-            }
-
-            try db.create(table: GroupMember.databaseTableName, ifNotExists: true) { table in
-                table.autoIncrementedPrimaryKey(GroupMember.Column.id.rawValue, onConflict: .replace)
-                table.column(GroupMember.Column.userId.rawValue, .blob).notNull()
-                table.column(GroupMember.Column.username.rawValue, .text).notNull()
-                table.column(GroupMember.Column.photo.rawValue, .blob)
-                table.column(GroupMember.Column.status.rawValue, .integer).notNull()
-                table.column(GroupMember.Column.groupId.rawValue, .blob).notNull()
-                    .references(
-                        Group.databaseTableName,
-                        column: Group.Column.groupId.rawValue,
-                        onDelete: .cascade,
-                        deferred: true
-                    )
-            }
-
-            try db.create(table: GroupMessage.databaseTableName, ifNotExists: true) { table in
-                table.autoIncrementedPrimaryKey(GroupMessage.Column.id.rawValue, onConflict: .replace)
-                table.column(GroupMessage.Column.uniqueId.rawValue, .blob)
-                table.column(GroupMessage.Column.roundId.rawValue, .integer)
-                table.column(GroupMessage.Column.groupId.rawValue, .blob).notNull()
-                table.column(GroupMessage.Column.sender.rawValue, .blob).notNull()
-                table.column(GroupMessage.Column.roundURL.rawValue, .text)
-                table.column(GroupMessage.Column.payload.rawValue, .text).notNull()
-                table.column(GroupMessage.Column.status.rawValue, .integer).notNull()
-                table.column(GroupMessage.Column.unread.rawValue, .boolean).notNull()
-                table.column(GroupMessage.Column.timestamp.rawValue, .integer).notNull()
-            }
-
-            try db.create(table: FileTransfer.databaseTableName, ifNotExists: true) { table in
-                table.autoIncrementedPrimaryKey(FileTransfer.Column.id.rawValue, onConflict: .replace)
-                table.column(FileTransfer.Column.tid.rawValue, .blob).notNull()
-                table.column(FileTransfer.Column.contact.rawValue, .blob).notNull()
-                table.column(FileTransfer.Column.fileName.rawValue, .text).notNull()
-                table.column(FileTransfer.Column.fileType.rawValue, .text).notNull()
-                table.column(FileTransfer.Column.isIncoming.rawValue, .boolean).notNull()
-            }
-        }
-
-        migrator.registerMigration("v1: Updating contact/group requests UI") { db in
-            try db.create(table: "temp_\(Group.databaseTableName)") { table in
-                table.autoIncrementedPrimaryKey(Group.Column.id.rawValue, onConflict: .replace)
-                table.column(Group.Column.groupId.rawValue, .blob).unique()
-                table.column(Group.Column.name.rawValue, .text).notNull()
-                table.column(Group.Column.leader.rawValue, .blob).notNull()
-                table.column(Group.Column.serialize.rawValue, .blob).notNull()
-                table.column(Group.Column.status.rawValue, .integer).notNull()
-                table.column(Group.Column.createdAt.rawValue, .datetime).notNull()
-            }
-
-            let oldRows = try Row.fetchCursor(db, sql: "SELECT * FROM \(Group.databaseTableName)")
-            while let row = try oldRows.next() {
-                let status: Group.Status
-
-                if row["accepted"] == true {
-                    status = .participating
-                } else {
-                    status = .pending
-                }
-
-                try db.execute(
-                    sql: "INSERT INTO temp_\(Group.databaseTableName) (id, groupId, name, leader, serialize, status, createdAt) VALUES (?, ?, ?, ?, ?, ?, ?)",
-                    arguments:
-                        [row["id"],
-                         row["groupId"],
-                         row["name"],
-                         row["leader"],
-                         row["serialize"],
-                         status.rawValue,
-                         Date()
-                        ])
-            }
-
-            try db.drop(table: Group.databaseTableName)
-            try db.rename(table: "temp_\(Group.databaseTableName)", to: Group.databaseTableName)
-        }
-
-        migrator.registerMigration("v2") { db in
-            try db.alter(table: Contact.databaseTableName) { table in
-                table.add(column: Contact.Column.isRecent.rawValue, .boolean)
-            }
-
-            try Contact.updateAll(db, Contact.Column.isRecent.set(to: false))
-        }
-
-        try migrator.migrate(databaseQueue)
-    }
-}