diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
index c3bd5fcf26697adfffb3f7e049ff2bc246cfc1f4..5c44bcc8966df3957442c068b02754e2ec93acda 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
@@ -1,8 +1,10 @@
 package org.briarproject.bramble.api.identity;
 
 import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 @NotNullByDefault
@@ -15,17 +17,13 @@ public interface IdentityManager {
 	LocalAuthor createLocalAuthor(String name);
 
 	/**
-	 * Registers the given local identity with the manager. The identity is
-	 * not stored until {@link #storeLocalAuthor()} is called.
+	 * Registers the given local identity with the manager. This method should
+	 * be called before {@link LifecycleManager#startServices(SecretKey)}. The
+	 * identity is stored when {@link LifecycleManager#startServices(SecretKey)}
+	 * is called.
 	 */
 	void registerLocalAuthor(LocalAuthor a);
 
-	/**
-	 * Stores the local identity registered with
-	 * {@link #registerLocalAuthor(LocalAuthor)}, if any.
-	 */
-	void storeLocalAuthor() throws DbException;
-
 	/**
 	 * Returns the cached local identity or loads it from the database.
 	 */
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java
index 2ef340a8729c2dacb432ff7b6ad56cc214011f8d..4abd4b8e3cab35a1074d4b2e410ff16b69122b05 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java
@@ -2,16 +2,17 @@ package org.briarproject.bramble.api.lifecycle;
 
 import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 
 import java.util.concurrent.ExecutorService;
 
 /**
- * Manages the lifecycle of the app, starting {@link Client Clients}, starting
- * and stopping {@link Service Services}, shutting down
- * {@link ExecutorService ExecutorServices}, and opening and closing the
- * {@link DatabaseComponent}.
+ * Manages the lifecycle of the app: opening and closing the
+ * {@link DatabaseComponent} starting and stopping {@link Service Services},
+ * and shutting down {@link ExecutorService ExecutorServices}.
  */
 @NotNullByDefault
 public interface LifecycleManager {
@@ -43,16 +44,17 @@ public interface LifecycleManager {
 	}
 
 	/**
-	 * Registers a {@link Service} to be started and stopped. This method
-	 * should be called before {@link #startServices(SecretKey)}.
+	 * Registers a hook to be called after the database is opened and before
+	 * {@link Service services} are started. This method should be called
+	 * before {@link #startServices(SecretKey)}.
 	 */
-	void registerService(Service s);
+	void registerOpenDatabaseHook(OpenDatabaseHook hook, Priority p);
 
 	/**
-	 * Registers a {@link Client} to be started. This method should be called
-	 * before {@link #startServices(SecretKey)}.
+	 * Registers a {@link Service} to be started and stopped. This method
+	 * should be called before {@link #startServices(SecretKey)}.
 	 */
-	void registerClient(Client c);
+	void registerService(Service s);
 
 	/**
 	 * Registers an {@link ExecutorService} to be shut down. This method
@@ -62,7 +64,7 @@ public interface LifecycleManager {
 
 	/**
 	 * Opens the {@link DatabaseComponent} using the given key and starts any
-	 * registered {@link Client Clients} and {@link Service Services}.
+	 * registered {@link Service Services}.
 	 */
 	StartResult startServices(SecretKey dbKey);
 
@@ -80,8 +82,7 @@ public interface LifecycleManager {
 
 	/**
 	 * Waits for the {@link DatabaseComponent} to be opened and all registered
-	 * {@link Client Clients} and {@link Service Services} to start before
-	 * returning.
+	 * {@link Service Services} to start before returning.
 	 */
 	void waitForStartup() throws InterruptedException;
 
@@ -97,4 +98,10 @@ public interface LifecycleManager {
 	 */
 	LifecycleState getLifecycleState();
 
+	interface OpenDatabaseHook {
+
+		enum Priority {EARLY, NORMAL, LATE}
+
+		void onDatabaseOpened(Transaction txn) throws DbException;
+	}
 }
\ No newline at end of file
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java
deleted file mode 100644
index 956d876a349259b33090560fbb5f4fadbd1ef099..0000000000000000000000000000000000000000
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Client.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.bramble.api.sync;
-
-import org.briarproject.bramble.api.db.DbException;
-import org.briarproject.bramble.api.db.Transaction;
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-
-@NotNullByDefault
-public interface Client {
-
-	/**
-	 * Called at startup to create any local state needed by the client.
-	 */
-	void createLocalState(Transaction txn) throws DbException;
-}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
index a7d515d2838e8803af07678622f58455f5a5f668..4207ecb53221268df011e84e393d550c6eade49c 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.AuthorFactory;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.util.logging.Logger;
@@ -14,15 +15,16 @@ import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
+import static java.util.logging.Logger.getLogger;
 import static org.briarproject.bramble.util.LogUtils.logDuration;
 import static org.briarproject.bramble.util.LogUtils.now;
 
 @ThreadSafe
 @NotNullByDefault
-class IdentityManagerImpl implements IdentityManager {
+class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook {
 
 	private static final Logger LOG =
-			Logger.getLogger(IdentityManagerImpl.class.getName());
+			getLogger(IdentityManagerImpl.class.getName());
 
 	private final DatabaseComponent db;
 	private final AuthorFactory authorFactory;
@@ -52,13 +54,13 @@ class IdentityManagerImpl implements IdentityManager {
 	}
 
 	@Override
-	public void storeLocalAuthor() throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		LocalAuthor cached = cachedAuthor;
 		if (cached == null) {
 			LOG.info("No local author to store");
 			return;
 		}
-		db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
+		db.addLocalAuthor(txn, cached);
 		LOG.info("Local author stored");
 	}
 
@@ -89,5 +91,4 @@ class IdentityManagerImpl implements IdentityManager {
 	private LocalAuthor loadLocalAuthor(Transaction txn) throws DbException {
 		return db.getLocalAuthors(txn).iterator().next();
 	}
-
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java
index 950c0f383b04ecb634ece46b93d0ab0b7f2e9b92..1457b89e01076e122bc25baab5bc9bba041554ad 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityModule.java
@@ -2,6 +2,7 @@ package org.briarproject.bramble.identity;
 
 import org.briarproject.bramble.api.identity.AuthorFactory;
 import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -9,6 +10,8 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.EARLY;
+
 @Module
 public class IdentityModule {
 
@@ -24,8 +27,9 @@ public class IdentityModule {
 
 	@Provides
 	@Singleton
-	IdentityManager provideIdentityManager(
+	IdentityManager provideIdentityManager(LifecycleManager lifecycleManager,
 			IdentityManagerImpl identityManager) {
+		lifecycleManager.registerOpenDatabaseHook(identityManager, EARLY);
 		return identityManager;
 	}
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
index da55a780cf57ab1f144f0a067abeccd4a0659cd8..a87d6bdf2d2425fb0045b44b5444d4f3eee0c259 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
@@ -1,5 +1,6 @@
 package org.briarproject.bramble.lifecycle;
 
+import org.briarproject.bramble.api.Pair;
 import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.db.DataTooNewException;
 import org.briarproject.bramble.api.db.DataTooOldException;
@@ -7,14 +8,14 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.MigrationListener;
 import org.briarproject.bramble.api.event.EventBus;
-import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority;
 import org.briarproject.bramble.api.lifecycle.Service;
 import org.briarproject.bramble.api.lifecycle.ServiceException;
 import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CountDownLatch;
@@ -25,9 +26,11 @@ import java.util.logging.Logger;
 import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
+import static java.util.Collections.sort;
 import static java.util.logging.Level.FINE;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
+import static java.util.logging.Logger.getLogger;
 import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
 import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
 import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
@@ -49,14 +52,13 @@ import static org.briarproject.bramble.util.LogUtils.now;
 class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
 
 	private static final Logger LOG =
-			Logger.getLogger(LifecycleManagerImpl.class.getName());
+			getLogger(LifecycleManagerImpl.class.getName());
 
 	private final DatabaseComponent db;
 	private final EventBus eventBus;
 	private final List<Service> services;
-	private final List<Client> clients;
+	private final List<Pair<OpenDatabaseHook, Priority>> openDatabaseHooks;
 	private final List<ExecutorService> executors;
-	private final IdentityManager identityManager;
 	private final Semaphore startStopSemaphore = new Semaphore(1);
 	private final CountDownLatch dbLatch = new CountDownLatch(1);
 	private final CountDownLatch startupLatch = new CountDownLatch(1);
@@ -65,13 +67,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
 	private volatile LifecycleState state = STARTING;
 
 	@Inject
-	LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
-			IdentityManager identityManager) {
+	LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus) {
 		this.db = db;
 		this.eventBus = eventBus;
-		this.identityManager = identityManager;
 		services = new CopyOnWriteArrayList<>();
-		clients = new CopyOnWriteArrayList<>();
+		openDatabaseHooks = new CopyOnWriteArrayList<>();
 		executors = new CopyOnWriteArrayList<>();
 	}
 
@@ -83,10 +83,12 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
 	}
 
 	@Override
-	public void registerClient(Client c) {
-		if (LOG.isLoggable(INFO))
-			LOG.info("Registering client " + c.getClass().getSimpleName());
-		clients.add(c);
+	public void registerOpenDatabaseHook(OpenDatabaseHook hook, Priority p) {
+		if (LOG.isLoggable(INFO)) {
+			LOG.info("Registering open database hook "
+					+ hook.getClass().getSimpleName());
+		}
+		openDatabaseHooks.add(new Pair<>(hook, p));
 	}
 
 	@Override
@@ -102,28 +104,31 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
 			return ALREADY_RUNNING;
 		}
 		try {
-			LOG.info("Starting services");
+			LOG.info("Opening database");
 			long start = now();
-
 			boolean reopened = db.open(dbKey, this);
 			if (reopened) logDuration(LOG, "Reopening database", start);
 			else logDuration(LOG, "Creating database", start);
-			identityManager.storeLocalAuthor();
-
-			state = STARTING_SERVICES;
-			dbLatch.countDown();
-			eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
-
+			List<Pair<OpenDatabaseHook, Priority>> hooks =
+					new ArrayList<>(openDatabaseHooks);
+			sort(hooks, (a, b) -> a.getSecond().compareTo(b.getSecond()));
 			db.transaction(false, txn -> {
-				for (Client c : clients) {
+				for (Pair<OpenDatabaseHook, Priority> pair : hooks) {
 					long start1 = now();
-					c.createLocalState(txn);
+					OpenDatabaseHook hook = pair.getFirst();
+					hook.onDatabaseOpened(txn);
 					if (LOG.isLoggable(FINE)) {
-						logDuration(LOG, "Starting client "
-								+ c.getClass().getSimpleName(), start1);
+						logDuration(LOG, "Calling open database hook "
+								+ hook.getClass().getSimpleName(), start1);
 					}
 				}
 			});
+
+			LOG.info("Starting services");
+			state = STARTING_SERVICES;
+			dbLatch.countDown();
+			eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
+
 			for (Service s : services) {
 				start = now();
 				s.startService();
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java
index a208f588179c23663e662de636f952280e4cbec0..5e668f2952da498409d9a537267e19f56b944def 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/PropertiesModule.java
@@ -15,6 +15,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
 import static org.briarproject.bramble.api.properties.TransportPropertyManager.MAJOR_VERSION;
 import static org.briarproject.bramble.api.properties.TransportPropertyManager.MINOR_VERSION;
@@ -48,7 +49,8 @@ public class PropertiesModule {
 			ValidationManager validationManager, ContactManager contactManager,
 			ClientVersioningManager clientVersioningManager,
 			TransportPropertyManagerImpl transportPropertyManager) {
-		lifecycleManager.registerClient(transportPropertyManager);
+		lifecycleManager.registerOpenDatabaseHook(transportPropertyManager,
+				NORMAL);
 		validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
 				transportPropertyManager);
 		contactManager.registerContactHook(transportPropertyManager);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
index 92cc32ed8232980c8b7449b3e351266cee5742a7..6549f070c5135912b9a3a1e758f66aa10e587d37 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
@@ -13,11 +13,11 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Metadata;
 import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.properties.TransportProperties;
 import org.briarproject.bramble.api.properties.TransportPropertyManager;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.Group.Visibility;
 import org.briarproject.bramble.api.sync.GroupId;
@@ -40,7 +40,8 @@ import javax.inject.Inject;
 @Immutable
 @NotNullByDefault
 class TransportPropertyManagerImpl implements TransportPropertyManager,
-		Client, ContactHook, ClientVersioningHook, IncomingMessageHook {
+		OpenDatabaseHook, ContactHook, ClientVersioningHook,
+		IncomingMessageHook {
 
 	private final DatabaseComponent db;
 	private final ClientHelper clientHelper;
@@ -67,7 +68,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		if (db.containsGroup(txn, localGroup.getId())) return;
 		db.addGroup(txn, localGroup);
 		// Set things up for any pre-existing contacts
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java
index ccc7b41bbfd586671f8e6a739ae58e1c0b1144ba..7e6dd41d5ac98513d6e68ce88b3b5314496e7e2a 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/versioning/ClientVersioningManagerImpl.java
@@ -12,10 +12,10 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Metadata;
 import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.lifecycle.Service;
 import org.briarproject.bramble.api.lifecycle.ServiceException;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.ClientId;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -53,8 +53,8 @@ import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_
 import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
 
 @NotNullByDefault
-class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
-		Service, ContactHook, IncomingMessageHook {
+class ClientVersioningManagerImpl implements ClientVersioningManager,
+		Service, OpenDatabaseHook, ContactHook, IncomingMessageHook {
 
 	private final DatabaseComponent db;
 	private final ClientHelper clientHelper;
@@ -124,7 +124,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		if (db.containsGroup(txn, localGroup.getId())) return;
 		db.addGroup(txn, localGroup);
 		// Set things up for any pre-existing contacts
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/versioning/VersioningModule.java b/bramble-core/src/main/java/org/briarproject/bramble/versioning/VersioningModule.java
index 070e90c76fd611796a153fd2f2e5c8d6ae59988c..dda209e37689583e99dce3b9223f2c78c983490b 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/versioning/VersioningModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/versioning/VersioningModule.java
@@ -14,6 +14,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.bramble.api.versioning.ClientVersioningManager.CLIENT_ID;
 import static org.briarproject.bramble.api.versioning.ClientVersioningManager.MAJOR_VERSION;
 
@@ -34,7 +35,8 @@ public class VersioningModule {
 			ClientVersioningManagerImpl clientVersioningManager,
 			LifecycleManager lifecycleManager, ContactManager contactManager,
 			ValidationManager validationManager) {
-		lifecycleManager.registerClient(clientVersioningManager);
+		lifecycleManager.registerOpenDatabaseHook(clientVersioningManager,
+				NORMAL);
 		lifecycleManager.registerService(clientVersioningManager);
 		contactManager.registerContactHook(clientVersioningManager);
 		validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
index 896b491562030f1d42808764e4a09696daa1fa43..7d8e220594640693ff1a7f4eed43ebde5ad6cba8 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.AuthorFactory;
-import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.briarproject.bramble.test.DbExpectations;
@@ -27,7 +26,7 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
 	private final LocalAuthor localAuthor = getLocalAuthor();
 	private final Collection<LocalAuthor> localAuthors =
 			singletonList(localAuthor);
-	private IdentityManager identityManager;
+	private IdentityManagerImpl identityManager;
 
 	@Before
 	public void setUp() {
@@ -35,15 +34,20 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
 	}
 
 	@Test
-	public void testRegisterAndStoreLocalAuthor() throws Exception {
+	public void testOpenDatabaseHookWithoutLocalAuthorRegistered()
+			throws Exception {
+		identityManager.onDatabaseOpened(txn);
+	}
+
+	@Test
+	public void testOpenDatabaseHookWithLocalAuthorRegistered()
+			throws Exception {
 		context.checking(new DbExpectations() {{
-			oneOf(db).transaction(with(false), withDbRunnable(txn));
 			oneOf(db).addLocalAuthor(txn, localAuthor);
 		}});
 
 		identityManager.registerLocalAuthor(localAuthor);
-		assertEquals(localAuthor, identityManager.getLocalAuthor());
-		identityManager.storeLocalAuthor();
+		identityManager.onDatabaseOpened(txn);
 	}
 
 	@Test
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java
index 80e338259a0e4c51a0e67130c2802a625854932f..8ec2e8631e2b3ad3fea50db20a51635deca28e9b 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyManagerImplTest.java
@@ -115,7 +115,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
 				1, true, true);
 
 		TransportPropertyManagerImpl t = createInstance();
-		t.createLocalState(txn);
+		t.onDatabaseOpened(txn);
 	}
 
 	@Test
@@ -129,7 +129,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
 		}});
 
 		TransportPropertyManagerImpl t = createInstance();
-		t.createLocalState(txn);
+		t.onDatabaseOpened(txn);
 	}
 
 	@Test
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java
index 21f6ccfe9f8e1020542c806c746387c2f29b8db6..5d4d627b2d6d86d498842626f0c2dd571e8ccd6e 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java
@@ -3,10 +3,10 @@ package org.briarproject.bramble.test;
 import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.lifecycle.IoExecutor;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority;
 import org.briarproject.bramble.api.lifecycle.Service;
 import org.briarproject.bramble.api.lifecycle.ShutdownManager;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
@@ -32,7 +32,8 @@ public class TestLifecycleModule {
 			}
 
 			@Override
-			public void registerClient(Client c) {
+			public void registerOpenDatabaseHook(OpenDatabaseHook hook,
+					Priority p) {
 			}
 
 			@Override
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/versioning/ClientVersioningManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/versioning/ClientVersioningManagerImplTest.java
index 6a15907911857f0bcac392ad71674968b54e752f..dd85557ead08d3d3a92f6560e0d36c72bb2640cf 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/versioning/ClientVersioningManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/versioning/ClientVersioningManagerImplTest.java
@@ -83,7 +83,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
 		expectAddingContact();
 
 		ClientVersioningManagerImpl c = createInstance();
-		c.createLocalState(txn);
+		c.onDatabaseOpened(txn);
 	}
 
 	@Test
@@ -95,7 +95,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
 		}});
 
 		ClientVersioningManagerImpl c = createInstance();
-		c.createLocalState(txn);
+		c.onDatabaseOpened(txn);
 	}
 
 	@Test
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
index d19d6d7eae26e282e7d125e89dee917c640cc771..c82cd4d30c096b401b1a24d4ef3979d41a0c62ea 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
@@ -56,6 +56,7 @@ import dagger.Provides;
 import static android.content.Context.MODE_PRIVATE;
 import static java.util.Arrays.asList;
 import static java.util.Collections.emptyList;
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
 import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
 
@@ -226,7 +227,7 @@ public class AppModule {
 	@Singleton
 	RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager,
 			RecentEmojiImpl recentEmoji) {
-		lifecycleManager.registerClient(recentEmoji);
+		lifecycleManager.registerOpenDatabaseHook(recentEmoji, NORMAL);
 		return recentEmoji;
 	}
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java
index ee349c1a591d5e2d47a7544227dcf0d3c7894cde..f751b46d6b03e7afd415973300d58f3b4d2cf8ac 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java
@@ -8,11 +8,11 @@ import com.vanniktech.emoji.emoji.Emoji;
 import org.briarproject.bramble.api.db.DatabaseExecutor;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
 import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.bramble.api.settings.Settings;
 import org.briarproject.bramble.api.settings.SettingsManager;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.system.AndroidExecutor;
 import org.briarproject.bramble.util.StringUtils;
 
@@ -30,7 +30,7 @@ import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
-class RecentEmojiImpl implements RecentEmoji, Client {
+class RecentEmojiImpl implements RecentEmoji, OpenDatabaseHook {
 
 	private static final Logger LOG =
 			Logger.getLogger(RecentEmojiImpl.class.getName());
@@ -72,7 +72,7 @@ class RecentEmojiImpl implements RecentEmoji, Client {
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		Settings settings =
 				settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
 		String serialized = settings.get(EMOJI_LRU_PREFERENCE);
diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
index de11cb1eab80ec9e85bab0bac711214589821aa7..3b24d49b229bdcc60119ec7b5dc869fefdee689e 100644
--- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
@@ -18,8 +18,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
 import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.Message;
@@ -68,7 +68,7 @@ import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
 
 @NotNullByDefault
 class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
-		ContactHook, Client {
+		OpenDatabaseHook, ContactHook {
 
 	private final ContactManager contactManager;
 	private final IdentityManager identityManager;
@@ -90,7 +90,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		// Create our personal blog if necessary
 		LocalAuthor a = identityManager.getLocalAuthor(txn);
 		Blog b = blogFactory.createBlog(a);
diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java
index 7e3873f365440b00ba2683eb288fdbf60d987581..ff60e9dd85f061590180fef7c60e0c48d22a3734 100644
--- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogModule.java
@@ -18,6 +18,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
 import static org.briarproject.briar.api.blog.BlogManager.MAJOR_VERSION;
 
@@ -36,7 +37,7 @@ public class BlogModule {
 	BlogManager provideBlogManager(BlogManagerImpl blogManager,
 			LifecycleManager lifecycleManager, ContactManager contactManager,
 			ValidationManager validationManager) {
-		lifecycleManager.registerClient(blogManager);
+		lifecycleManager.registerOpenDatabaseHook(blogManager, NORMAL);
 		contactManager.registerContactHook(blogManager);
 		validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
 				blogManager);
diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
index cea1e169ff27f6478bffb218a0e2888d682c8c44..04350c8a6723887c1fca9deab05789942b38b62b 100644
--- a/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedManagerImpl.java
@@ -20,11 +20,11 @@ import org.briarproject.bramble.api.event.Event;
 import org.briarproject.bramble.api.event.EventListener;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.plugin.TorConstants;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.system.Clock;
@@ -32,6 +32,7 @@ import org.briarproject.bramble.api.system.Scheduler;
 import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.blog.Blog;
 import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogManager.RemoveBlogHook;
 import org.briarproject.briar.api.blog.BlogPost;
 import org.briarproject.briar.api.blog.BlogPostFactory;
 import org.briarproject.briar.api.feed.Feed;
@@ -75,8 +76,8 @@ import static org.briarproject.briar.util.HtmlUtils.clean;
 
 @ThreadSafe
 @NotNullByDefault
-class FeedManagerImpl implements FeedManager, Client, EventListener,
-		BlogManager.RemoveBlogHook {
+class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook,
+		RemoveBlogHook {
 
 	private static final Logger LOG =
 			Logger.getLogger(FeedManagerImpl.class.getName());
@@ -136,7 +137,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		Group g = getLocalGroup();
 		// Return if we've already set the local group up
 		if (db.containsGroup(txn, g.getId())) return;
diff --git a/briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java b/briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java
index c4b567c189977888c2e2927fc956e9cb2c40f079..5b82fa948e4b0f165707ffe2b56123f96d4b9ba2 100644
--- a/briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/feed/FeedModule.java
@@ -11,6 +11,8 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
+
 @Module
 public class FeedModule {
 
@@ -24,8 +26,7 @@ public class FeedModule {
 	FeedManager provideFeedManager(FeedManagerImpl feedManager,
 			LifecycleManager lifecycleManager, EventBus eventBus,
 			BlogManager blogManager) {
-
-		lifecycleManager.registerClient(feedManager);
+		lifecycleManager.registerOpenDatabaseHook(feedManager, NORMAL);
 		eventBus.addListener(feedManager);
 		blogManager.registerRemoveBlogHook(feedManager);
 		return feedManager;
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
index fd9f00804a49a572b4f564c52e9a463bfe8fe4f3..abe54aa7ac19ab3cd335310bbb0960ff7a665655 100644
--- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
@@ -19,8 +19,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
 import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.Group.Visibility;
 import org.briarproject.bramble.api.sync.GroupId;
@@ -67,7 +67,7 @@ import static org.briarproject.briar.introduction.MessageType.REQUEST;
 @Immutable
 @NotNullByDefault
 class IntroductionManagerImpl extends ConversationClientImpl
-		implements IntroductionManager, Client, ContactHook,
+		implements IntroductionManager, OpenDatabaseHook, ContactHook,
 		ClientVersioningHook {
 
 	private final ClientVersioningManager clientVersioningManager;
@@ -115,7 +115,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		// Create a local group to store protocol sessions
 		if (db.containsGroup(txn, localGroup.getId())) return;
 		db.addGroup(txn, localGroup);
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
index be80647d551d91ffad6eb0b86fcddc57587e31b2..4f326ba2ef4048ff5cc9edf2452d75d4234f3327 100644
--- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
@@ -16,6 +16,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_ID;
 import static org.briarproject.briar.api.introduction.IntroductionManager.MAJOR_VERSION;
 import static org.briarproject.briar.api.introduction.IntroductionManager.MINOR_VERSION;
@@ -51,7 +52,7 @@ public class IntroductionModule {
 			ConversationManager conversationManager,
 			ClientVersioningManager clientVersioningManager,
 			IntroductionManagerImpl introductionManager) {
-		lifecycleManager.registerClient(introductionManager);
+		lifecycleManager.registerOpenDatabaseHook(introductionManager, NORMAL);
 		contactManager.registerContactHook(introductionManager);
 		validationManager.registerIncomingMessageHook(CLIENT_ID,
 				MAJOR_VERSION, introductionManager);
diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java
index 2dbd584bef985d452c1ae741c45306ee613eaf49..44073b3776507d81b9eadac0170bee98364bb5fd 100644
--- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java
@@ -12,8 +12,8 @@ import org.briarproject.bramble.api.data.MetadataParser;
 import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.Group.Visibility;
 import org.briarproject.bramble.api.sync.GroupId;
@@ -50,7 +50,8 @@ import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ
 @Immutable
 @NotNullByDefault
 class MessagingManagerImpl extends ConversationClientImpl
-		implements MessagingManager, Client, ContactHook, ClientVersioningHook {
+		implements MessagingManager, OpenDatabaseHook, ContactHook,
+		ClientVersioningHook {
 
 	private final ClientVersioningManager clientVersioningManager;
 	private final ContactGroupFactory contactGroupFactory;
@@ -66,7 +67,7 @@ class MessagingManagerImpl extends ConversationClientImpl
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		// Create a local group to indicate that we've set this client up
 		Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
 				MAJOR_VERSION);
diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java
index c806ebea3417e1ec84a7b6294115f0e565f732f5..2a64fd1cdc548ab374ef01c544291692e0122901 100644
--- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingModule.java
@@ -17,6 +17,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.briar.api.messaging.MessagingManager.CLIENT_ID;
 import static org.briarproject.briar.api.messaging.MessagingManager.MAJOR_VERSION;
 import static org.briarproject.briar.api.messaging.MessagingManager.MINOR_VERSION;
@@ -58,7 +59,7 @@ public class MessagingModule {
 			ConversationManager conversationManager,
 			ClientVersioningManager clientVersioningManager,
 			MessagingManagerImpl messagingManager) {
-		lifecycleManager.registerClient(messagingManager);
+		lifecycleManager.registerOpenDatabaseHook(messagingManager, NORMAL);
 		contactManager.registerContactHook(messagingManager);
 		validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
 				messagingManager);
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
index c252ac7879705eaa9143edd74a8edd7f57305c23..8cd75d090b5d17a31fe3e5c808ad36dd34b3fcad 100644
--- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java
@@ -14,8 +14,8 @@ import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Metadata;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.Group.Visibility;
 import org.briarproject.bramble.api.sync.GroupId;
@@ -62,7 +62,7 @@ import static org.briarproject.briar.privategroup.invitation.Role.PEER;
 @Immutable
 @NotNullByDefault
 class GroupInvitationManagerImpl extends ConversationClientImpl
-		implements GroupInvitationManager, Client, ContactHook,
+		implements GroupInvitationManager, OpenDatabaseHook, ContactHook,
 		PrivateGroupHook, ClientVersioningHook {
 
 	private final ClientVersioningManager clientVersioningManager;
@@ -101,7 +101,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
 	}
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		// Create a local group to indicate that we've set this client up
 		Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
 				MAJOR_VERSION);
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java
index 6960dae6bd8af24c5f04de05b386bf2951b9ab78..7ec8512c61fc7ba360c79183bcd8b42f74595e60 100644
--- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationModule.java
@@ -19,6 +19,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
 import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
 import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.MAJOR_VERSION;
 import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.MINOR_VERSION;
@@ -42,7 +43,8 @@ public class GroupInvitationModule {
 			PrivateGroupManager privateGroupManager,
 			ConversationManager conversationManager,
 			ClientVersioningManager clientVersioningManager) {
-		lifecycleManager.registerClient(groupInvitationManager);
+		lifecycleManager.registerOpenDatabaseHook(groupInvitationManager,
+				NORMAL);
 		validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
 				groupInvitationManager);
 		contactManager.registerContactHook(groupInvitationManager);
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
index 38a45c5e5036211a7f9ff7de74b2ca9159aca7ce..481d65f09be72f9dd4af54a731b8d5ad8758f449 100644
--- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java
@@ -13,8 +13,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Metadata;
 import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.ClientId;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -55,7 +55,7 @@ import static org.briarproject.briar.sharing.State.SHARING;
 @NotNullByDefault
 abstract class SharingManagerImpl<S extends Shareable>
 		extends ConversationClientImpl
-		implements SharingManager<S>, Client, ContactHook,
+		implements SharingManager<S>, OpenDatabaseHook, ContactHook,
 		ClientVersioningHook {
 
 	private final ClientVersioningManager clientVersioningManager;
@@ -92,7 +92,7 @@ abstract class SharingManagerImpl<S extends Shareable>
 	protected abstract int getShareableMajorVersion();
 
 	@Override
-	public void createLocalState(Transaction txn) throws DbException {
+	public void onDatabaseOpened(Transaction txn) throws DbException {
 		// Create a local group to indicate that we've set this client up
 		Group localGroup = contactGroupFactory.createLocalGroup(getClientId(),
 				getMajorVersion());
diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java
index a71d215af18d6c89be2a7fd397267dbce8d9e8dc..8d460f36966c820cd1854241c1097e219e3f48ed 100644
--- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingModule.java
@@ -25,6 +25,8 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook.Priority.NORMAL;
+
 @Module
 public class SharingModule {
 
@@ -76,7 +78,7 @@ public class SharingModule {
 			ConversationManager conversationManager, BlogManager blogManager,
 			ClientVersioningManager clientVersioningManager,
 			BlogSharingManagerImpl blogSharingManager) {
-		lifecycleManager.registerClient(blogSharingManager);
+		lifecycleManager.registerOpenDatabaseHook(blogSharingManager, NORMAL);
 		contactManager.registerContactHook(blogSharingManager);
 		validationManager.registerIncomingMessageHook(
 				BlogSharingManager.CLIENT_ID, BlogSharingManager.MAJOR_VERSION,
@@ -135,7 +137,7 @@ public class SharingModule {
 			ConversationManager conversationManager, ForumManager forumManager,
 			ClientVersioningManager clientVersioningManager,
 			ForumSharingManagerImpl forumSharingManager) {
-		lifecycleManager.registerClient(forumSharingManager);
+		lifecycleManager.registerOpenDatabaseHook(forumSharingManager, NORMAL);
 		contactManager.registerContactHook(forumSharingManager);
 		validationManager.registerIncomingMessageHook(
 				ForumSharingManager.CLIENT_ID,
diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
index 7099c5ed758af4cd25b559206f78f33f2873fed7..b4057381585f1707d3369f9707417ea94de4f9df 100644
--- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
@@ -112,7 +112,7 @@ public class BlogManagerImplTest extends BriarTestCase {
 	}
 
 	@Test
-	public void testCreateLocalState() throws DbException {
+	public void testOpenDatabaseHook() throws DbException {
 		Transaction txn = new Transaction(null, false);
 
 		context.checking(new Expectations() {{
@@ -123,7 +123,7 @@ public class BlogManagerImplTest extends BriarTestCase {
 			oneOf(db).addGroup(txn, blog1.getGroup());
 		}});
 
-		blogManager.createLocalState(txn);
+		blogManager.onDatabaseOpened(txn);
 		context.assertIsSatisfied();
 	}
 
diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
index ca88b7285ffd53878a09ebbe7a3b8d0a98162966..bba390590bb3e2a9af2b3f53ba442634033edd2a 100644
--- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
@@ -149,7 +149,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
 	}
 
 	@Test
-	public void testCreateLocalStateFirstTime() throws Exception {
+	public void testDatabaseOpenHookFirstTime() throws Exception {
 		context.checking(new Expectations() {{
 			oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
 					MAJOR_VERSION);
@@ -161,11 +161,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
 			will(returnValue(Collections.singletonList(contact)));
 		}});
 		expectAddingContact(contact);
-		groupInvitationManager.createLocalState(txn);
+		groupInvitationManager.onDatabaseOpened(txn);
 	}
 
 	@Test
-	public void testCreateLocalStateSubsequentTime() throws Exception {
+	public void testOpenDatabaseHookSubsequentTime() throws Exception {
 		context.checking(new Expectations() {{
 			oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
 					MAJOR_VERSION);
@@ -173,7 +173,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
 			oneOf(db).containsGroup(txn, localGroup.getId());
 			will(returnValue(true));
 		}});
-		groupInvitationManager.createLocalState(txn);
+		groupInvitationManager.onDatabaseOpened(txn);
 	}
 
 	private void expectAddingContact(Contact c) throws Exception {
diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java
index ab14d8fdf913494992e51882a8e6703520fb4d35..e89e37c0d7c72ba007bc33ca116e6a4da18d16a7 100644
--- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingManagerImplTest.java
@@ -94,7 +94,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
 	}
 
 	@Test
-	public void testCreateLocalStateFirstTimeWithExistingContact()
+	public void testOpenDatabaseHookFirstTimeWithExistingContact()
 			throws Exception {
 		Transaction txn = new Transaction(null, false);
 
@@ -113,7 +113,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
 		// Set things up for the contact
 		expectAddingContact(txn);
 
-		blogSharingManager.createLocalState(txn);
+		blogSharingManager.onDatabaseOpened(txn);
 	}
 
 	private void expectAddingContact(Transaction txn) throws Exception {
@@ -149,7 +149,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
 	}
 
 	@Test
-	public void testCreateLocalStateSubsequentTime() throws Exception {
+	public void testOpenDatabaseHookSubsequentTime() throws Exception {
 		Transaction txn = new Transaction(null, false);
 
 		context.checking(new Expectations() {{
@@ -161,7 +161,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
 			will(returnValue(true));
 		}});
 
-		blogSharingManager.createLocalState(txn);
+		blogSharingManager.onDatabaseOpened(txn);
 	}
 
 	@Test