diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
index 85f8c57163a72b7a2d585540d1f8e12d5e19b672..515f8f81a4aace821656a0a513fddf234b256328 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
@@ -437,6 +437,16 @@ public interface DatabaseComponent {
 	 */
 	long getNextSendTime(Transaction txn, ContactId c) throws DbException;
 
+
+	/**
+	 * Checks whether messages or ACKs need to be delivered
+	 * to the given contact at the current time
+	 * <p />
+	 * Read-only.
+	 */
+	boolean hasMessagesOrAcksToSend(Transaction transaction,
+			ContactId c) throws DbException;
+
 	/**
 	 * Returns all settings in the given namespace.
 	 * <p/>
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
index 2cc17ca6183429dcff632600a15889be60a34d09..1081c4399785ec8c6bce1ed59b7efc7bdf9b18dd 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
@@ -505,6 +505,14 @@ interface Database<T> {
 	 */
 	long getNextSendTime(T txn, ContactId c) throws DbException;
 
+	/**
+	 * Checks whether messages or ACKs need to be delivered
+	 * to the given contact at the current time
+	 * <p />
+	 * Read-only.
+	 */
+	boolean hasMessagesToSend(T txn, ContactId c) throws DbException;
+
 	/**
 	 * Returns the IDs of some messages that are eligible to be sent to the
 	 * given contact and have been requested by the contact, up to the given
@@ -689,4 +697,5 @@ interface Database<T> {
 	 * Updates the given transport keys following key rotation.
 	 */
 	void updateTransportKeys(T txn, KeySet ks) throws DbException;
+
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
index 5a2f8325111ddba996420ef5768102fd4c330695..855c47fa301643a34d1e182f6d13c9e630b88d2c 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
@@ -304,6 +304,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		db.deleteMessageMetadata(txn, m);
 	}
 
+	@Override
+	public boolean hasMessagesOrAcksToSend(Transaction transaction,
+			ContactId c) throws DbException {
+		T txn = unbox(transaction);
+		if (!db.containsContact(txn, c))
+			throw new NoSuchContactException();
+		return db.hasMessagesToSend(txn, c);
+	}
+
 	@Nullable
 	@Override
 	public Ack generateAck(Transaction transaction, ContactId c,
@@ -425,7 +434,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 	}
 
 	@Override
-	public ContactType getContactType(Transaction transaction, ContactId contactId) throws DbException {
+	public ContactType getContactType(Transaction transaction,
+			ContactId contactId) throws DbException {
 		T txn = unbox(transaction);
 		return db.getContactType(txn, contactId);
 	}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
index e952cf58720412f7ecca20a7f48d6a5459d70913..132f3b8de0c1a42aaad7f4257d26643236c9027f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
@@ -2186,6 +2186,36 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
+	public boolean hasMessagesToSend(Connection txn, ContactId c)
+			throws DbException {
+		PreparedStatement ps = null;
+		ResultSet rs = null;
+		long now = clock.currentTimeMillis();
+		try {
+			String sql = "SELECT messageId FROM statuses"
+					+ " WHERE contactId = ?"
+					+ " AND ((ack = TRUE) OR (state = ?"
+					+ " AND groupShared = TRUE AND messageShared = TRUE"
+					+ " AND deleted = FALSE AND seen = FALSE"
+					+ " AND expiry < ?))"
+					+ " LIMIT 1";
+			ps = txn.prepareStatement(sql);
+			ps.setInt(1, c.getInt());
+			ps.setInt(2, DELIVERED.getValue());
+			ps.setLong(3, now);
+			rs = ps.executeQuery();
+			List<MessageId> ids = new ArrayList<>();
+			while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
+			rs.close();
+			ps.close();
+			return ids.size() > 0;
+		} catch (SQLException e) {
+			tryToClose(rs);
+			tryToClose(ps);
+			throw new DbException(e);
+		}
+	}
+
 	@Override
 	public Collection<MessageId> getRequestedMessagesToSend(Connection txn,
 			ContactId c, int maxLength) throws DbException {