diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
index 8fb1a905bf80dfa6b054f44c5926abe88f145fe9..6ce8e79a879444e6a901ba5084beb01e7340589a 100644
--- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java
+++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
@@ -97,6 +97,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 					+ " (contactId INT NOT NULL,"
 					+ " groupId HASH NOT NULL,"
 					+ " inbox BOOLEAN NOT NULL,"
+					+ " PRIMARY KEY (contactId, groupId),"
 					+ " FOREIGN KEY (contactId)"
 					+ " REFERENCES contacts (contactId)"
 					+ " ON DELETE CASCADE,"
@@ -156,21 +157,12 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private static final String INDEX_MESSAGES_BY_TIMESTAMP =
 			"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
 
-	// Locking: message
-	private static final String CREATE_MESSAGES_TO_ACK =
-			"CREATE TABLE messagesToAck"
-					+ " (messageId HASH NOT NULL," // Not a foreign key
-					+ " contactId INT NOT NULL,"
-					+ " PRIMARY KEY (messageId, contactId),"
-					+ " FOREIGN KEY (contactId)"
-					+ " REFERENCES contacts (contactId)"
-					+ " ON DELETE CASCADE)";
-
 	// Locking: message
 	private static final String CREATE_STATUSES =
 			"CREATE TABLE statuses"
 					+ " (messageId HASH NOT NULL,"
 					+ " contactId INT NOT NULL,"
+					+ " ack BOOLEAN NOT NULL,"
 					+ " seen BOOLEAN NOT NULL,"
 					+ " expiry BIGINT NOT NULL,"
 					+ " txCount INT NOT NULL,"
@@ -374,7 +366,6 @@ abstract class JdbcDatabase implements Database<Connection> {
 			s.executeUpdate(insertTypeNames(CREATE_GROUP_VERSIONS));
 			s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
 			s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
-			s.executeUpdate(insertTypeNames(CREATE_MESSAGES_TO_ACK));
 			s.executeUpdate(insertTypeNames(CREATE_STATUSES));
 			s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
 			s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
@@ -749,24 +740,13 @@ abstract class JdbcDatabase implements Database<Connection> {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
-			String sql = "SELECT NULL FROM messagesToAck"
+			String sql = "UPDATE statuses SET ack = TRUE"
 					+ " WHERE messageId = ? AND contactId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getBytes());
 			ps.setInt(2, c.getInt());
-			rs = ps.executeQuery();
-			boolean found = rs.next();
-			if(rs.next()) throw new DbStateException();
-			rs.close();
-			ps.close();
-			if(found) return;
-			sql = "INSERT INTO messagesToAck (messageId, contactId)"
-					+ " VALUES (?, ?)";
-			ps = txn.prepareStatement(sql);
-			ps.setBytes(1, m.getBytes());
-			ps.setInt(2, c.getInt());
 			int affected = ps.executeUpdate();
-			if(affected != 1) throw new DbStateException();
+			if(affected > 1) throw new DbStateException();
 			ps.close();
 		} catch(SQLException e) {
 			tryToClose(rs);
@@ -826,8 +806,8 @@ abstract class JdbcDatabase implements Database<Connection> {
 		PreparedStatement ps = null;
 		try {
 			String sql = "INSERT INTO statuses"
-					+ " (messageId, contactId, seen, expiry, txCount)"
-					+ " VALUES (?, ?, ?, 0, 0)";
+					+ " (messageId, contactId, ack, seen, expiry, txCount)"
+					+ " VALUES (?, ?, FALSE, ?, 0, 0)";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getBytes());
 			ps.setInt(2, c.getInt());
@@ -1644,8 +1624,8 @@ abstract class JdbcDatabase implements Database<Connection> {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
-			String sql = "SELECT messageId FROM messagesToAck"
-					+ " WHERE contactId = ?"
+			String sql = "SELECT messageId FROM statuses"
+					+ " WHERE contactId = ? AND ack = TRUE"
 					+ " LIMIT ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
@@ -2548,7 +2528,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			Collection<MessageId> acked) throws DbException {
 		PreparedStatement ps = null;
 		try {
-			String sql = "DELETE FROM messagesToAck"
+			String sql = "UPDATE statuses SET ack = FALSE"
 					+ " WHERE contactId = ? AND messageId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
index 0fc598ffd085e9a6f677841f78094b3b31d63497..99c74b2ade651189463057a1b138a47542eb9545 100644
--- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
+++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
@@ -299,11 +299,21 @@ public class H2DatabaseTest extends BriarTestCase {
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
-		// Add a contact and some messages to ack
-		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
+		// Add a contact and subscribe to a group
 		db.addLocalAuthor(txn, localAuthor);
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
+		db.addGroup(txn, group);
+		db.setGroups(txn, contactId, Arrays.asList(group), 1);
+
+		// Add some messages to ack
+		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
+		Message message1 = new TestMessage(messageId1, null, group, author,
+				contentType, subject, timestamp, raw);
+		db.addMessage(txn, message, false);
+		db.addStatus(txn, contactId, messageId, true);
 		db.addMessageToAck(txn, contactId, messageId);
+		db.addMessage(txn, message1, false);
+		db.addStatus(txn, contactId, messageId1, true);
 		db.addMessageToAck(txn, contactId, messageId1);
 
 		// Both message IDs should be returned
@@ -326,9 +336,15 @@ public class H2DatabaseTest extends BriarTestCase {
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
-		// Add a contact and receive the same message twice
+		// Add a contact and subscribe to a group
 		db.addLocalAuthor(txn, localAuthor);
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
+		db.addGroup(txn, group);
+		db.setGroups(txn, contactId, Arrays.asList(group), 1);
+
+		// Receive the same message twice
+		db.addMessage(txn, message, false);
+		db.addStatus(txn, contactId, messageId, true);
 		db.addMessageToAck(txn, contactId, messageId);
 		db.addMessageToAck(txn, contactId, messageId);