diff --git a/api/net/sf/briar/api/db/DatabaseDirectory.java b/api/net/sf/briar/api/db/DatabaseDirectory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed5fcdc0ec0b1653c0384619735bef04935323ca
--- /dev/null
+++ b/api/net/sf/briar/api/db/DatabaseDirectory.java
@@ -0,0 +1,15 @@
+package net.sf.briar.api.db;
+
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import com.google.inject.BindingAnnotation;
+
+/** Annotation for injecting the directory where the database is stored. */
+@BindingAnnotation
+@Target({ PARAMETER })
+@Retention(RUNTIME)
+public @interface DatabaseDirectory {}
diff --git a/api/net/sf/briar/api/db/DatabaseMaxSize.java b/api/net/sf/briar/api/db/DatabaseMaxSize.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec1a2fbae52f9da11edd834ed2bb1e9d92cfdb8d
--- /dev/null
+++ b/api/net/sf/briar/api/db/DatabaseMaxSize.java
@@ -0,0 +1,15 @@
+package net.sf.briar.api.db;
+
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import com.google.inject.BindingAnnotation;
+
+/** Annotation for injecting the maximum size in bytes of the database. */
+@BindingAnnotation
+@Target({ PARAMETER })
+@Retention(RUNTIME)
+public @interface DatabaseMaxSize {}
diff --git a/components/net/sf/briar/db/DatabaseCleaner.java b/components/net/sf/briar/db/DatabaseCleaner.java
index 635bc047f49bd447f2e7e5966977bd185acda8c5..25987e0d22a2de0ccd10e488fd6e4b595258dafb 100644
--- a/components/net/sf/briar/db/DatabaseCleaner.java
+++ b/components/net/sf/briar/db/DatabaseCleaner.java
@@ -6,9 +6,10 @@ interface DatabaseCleaner {
 
 	/**
 	 * Starts a new thread to monitor the amount of free storage space
-	 * available to the database and expire old messages as necessary.
+	 * available to the database and expire old messages as necessary. The
+	 * cleaner will pause for the given number of milliseconds between sweeps.
 	 */
-	void startCleaning();
+	void startCleaning(Callback callback, long msBetweenSweeps);
 
 	/** Tells the cleaner thread to exit and returns when it has done so. */
 	void stopCleaning();
@@ -18,9 +19,9 @@ interface DatabaseCleaner {
 		/**
 		 * Checks how much free storage space is available to the database, and
 		 * if necessary expires old messages until the free space is at least
-		 * MIN_FREE_SPACE. While the free space is less than
-		 * CRITICAL_FREE_SPACE, operations that attempt to store messages in
-		 * the database will block.
+		 * DatabaseConstants.MIN_FREE_SPACE. While the free space is less than
+		 * DatabaseConstants.CRITICAL_FREE_SPACE, operations that attempt to
+		 * store messages in the database will block.
 		 */
 		void checkFreeSpaceAndClean() throws DbException;
 
diff --git a/components/net/sf/briar/db/DatabaseCleanerImpl.java b/components/net/sf/briar/db/DatabaseCleanerImpl.java
index bd9dfc7f591c1ce81e2b478530be72ea86e3289a..6cf560738c28adf0a52f75160e7cb36d0299f5bd 100644
--- a/components/net/sf/briar/db/DatabaseCleanerImpl.java
+++ b/components/net/sf/briar/db/DatabaseCleanerImpl.java
@@ -2,22 +2,17 @@ package net.sf.briar.db;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import com.google.inject.Inject;
-
 class DatabaseCleanerImpl implements DatabaseCleaner, Runnable {
 
-	private final Callback db;
-	private final int msBetweenSweeps;
 	private final AtomicBoolean stopped = new AtomicBoolean(false);
 	private final Thread cleanerThread = new Thread(this);
 
-	@Inject
-	DatabaseCleanerImpl(Callback db, int msBetweenSweeps) {
-		this.db = db;
-		this.msBetweenSweeps = msBetweenSweeps;
-	}
+	private volatile Callback callback;
+	private volatile long msBetweenSweeps;
 
-	public void startCleaning() {
+	public void startCleaning(Callback callback, long msBetweenSweeps) {
+		this.callback = callback;
+		this.msBetweenSweeps = msBetweenSweeps;
 		cleanerThread.start();
 	}
 
@@ -35,8 +30,8 @@ class DatabaseCleanerImpl implements DatabaseCleaner, Runnable {
 	public void run() {
 		try {
 			while(!stopped.get()) {
-				if(db.shouldCheckFreeSpace()) {
-					db.checkFreeSpaceAndClean();
+				if(callback.shouldCheckFreeSpace()) {
+					callback.checkFreeSpaceAndClean();
 				} else {
 					synchronized(stopped) {
 						try {
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index c43c778a2ace0c9f9cf227d51c00d9201ae5ff7f..4f269012fbf667d5ec1f870831a666df4eba83e0 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -99,7 +99,7 @@ DatabaseCleaner.Callback {
 
 	public void open(boolean resume) throws DbException {
 		db.open(resume);
-		cleaner.startCleaning();
+		cleaner.startCleaning(this, MAX_MS_BETWEEN_SPACE_CHECKS);
 	}
 
 	public void close() throws DbException {
diff --git a/components/net/sf/briar/db/DatabaseConstants.java b/components/net/sf/briar/db/DatabaseConstants.java
index 54b4feebc7aa4f511999c7c58b93946f897c0a93..e2c29910626cd6aa33bafec934e37168fd01a5c9 100644
--- a/components/net/sf/briar/db/DatabaseConstants.java
+++ b/components/net/sf/briar/db/DatabaseConstants.java
@@ -2,13 +2,15 @@ package net.sf.briar.db;
 
 interface DatabaseConstants {
 
-	static final int MEGABYTE = 1024 * 1024;
-
 	// FIXME: These should be configurable
-	static final long MIN_FREE_SPACE = 300L * MEGABYTE;
-	static final long CRITICAL_FREE_SPACE = 100L * MEGABYTE;
-	static final int MAX_BYTES_BETWEEN_SPACE_CHECKS = 5 * MEGABYTE;
+	static final long MIN_FREE_SPACE = 300 * 1024 * 1024; // 300 MiB
+	static final long CRITICAL_FREE_SPACE = 100 * 1024 * 1024; // 100 MiB
+
+	static final int MAX_BYTES_BETWEEN_SPACE_CHECKS = 5 * 1024 * 1024; // 5 MiB
 	static final long MAX_MS_BETWEEN_SPACE_CHECKS = 60L * 1000L; // 1 min
-	static final int BYTES_PER_SWEEP = 5 * MEGABYTE;
+
+	static final long MS_PER_SWEEP = 10L * 1000L; // 10 sec
+	static final int BYTES_PER_SWEEP = 5 * 1024 * 1024; // 5 MiB
+
 	static final long EXPIRY_MODULUS = 60L * 60L * 1000L; // 1 hour
 }
diff --git a/components/net/sf/briar/db/DatabaseModule.java b/components/net/sf/briar/db/DatabaseModule.java
index 218b768438c5b81093f65fc1110a691b374f412b..903fb43458772d61ca785b05757753a4412554a0 100644
--- a/components/net/sf/briar/db/DatabaseModule.java
+++ b/components/net/sf/briar/db/DatabaseModule.java
@@ -1,16 +1,39 @@
 package net.sf.briar.db;
 
+import java.io.File;
+import java.sql.Connection;
+
+import net.sf.briar.api.crypto.Password;
 import net.sf.briar.api.db.DatabaseComponent;
+import net.sf.briar.api.db.DatabaseDirectory;
+import net.sf.briar.api.db.DatabaseMaxSize;
+import net.sf.briar.api.db.DatabasePassword;
+import net.sf.briar.api.protocol.GroupFactory;
+import net.sf.briar.api.transport.ConnectionWindowFactory;
 
 import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
 import com.google.inject.Singleton;
 
 public class DatabaseModule extends AbstractModule {
 
 	@Override
 	protected void configure() {
-		bind(Database.class).to(H2Database.class);
-		bind(DatabaseComponent.class).to(DatabaseComponentImpl.class).in(
-				Singleton.class);
+		bind(DatabaseCleaner.class).to(DatabaseCleanerImpl.class);
+	}
+
+	@Provides
+	Database<Connection> getDatabase(@DatabaseDirectory File dir,
+			@DatabasePassword Password password, @DatabaseMaxSize long maxSize,
+			ConnectionWindowFactory connectionWindowFactory,
+			GroupFactory groupFactory) {
+		return new H2Database(dir, password, maxSize, connectionWindowFactory,
+				groupFactory);
+	}
+
+	@Provides @Singleton
+	DatabaseComponent getDatabaseComponent(Database<Connection> db,
+			DatabaseCleaner cleaner) {
+		return new DatabaseComponentImpl<Connection>(db, cleaner);
 	}
 }
diff --git a/components/net/sf/briar/db/H2Database.java b/components/net/sf/briar/db/H2Database.java
index 6a1548f75345da8b6853f0b81faf98cc8bf4e766..9bfcb69ebf1d7967ac8091df80015fcf4499e32b 100644
--- a/components/net/sf/briar/db/H2Database.java
+++ b/components/net/sf/briar/db/H2Database.java
@@ -11,6 +11,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.sf.briar.api.crypto.Password;
+import net.sf.briar.api.db.DatabaseDirectory;
+import net.sf.briar.api.db.DatabaseMaxSize;
 import net.sf.briar.api.db.DatabasePassword;
 import net.sf.briar.api.db.DbException;
 import net.sf.briar.api.protocol.GroupFactory;
@@ -32,7 +34,8 @@ class H2Database extends JdbcDatabase {
 	private final long maxSize;
 
 	@Inject
-	H2Database(File dir, @DatabasePassword Password password, long maxSize,
+	H2Database(@DatabaseDirectory File dir, @DatabasePassword Password password,
+			@DatabaseMaxSize long maxSize,
 			ConnectionWindowFactory connectionWindowFactory,
 			GroupFactory groupFactory) {
 		super(connectionWindowFactory, groupFactory, "BINARY(32)", "BINARY");
diff --git a/test/net/sf/briar/db/DatabaseCleanerImplTest.java b/test/net/sf/briar/db/DatabaseCleanerImplTest.java
index 1042338aea4e5afb3cac0dbbfcf5d934545f8b76..0ccf73824273b4293090514266188bc8b9d66a0f 100644
--- a/test/net/sf/briar/db/DatabaseCleanerImplTest.java
+++ b/test/net/sf/briar/db/DatabaseCleanerImplTest.java
@@ -25,17 +25,15 @@ public class DatabaseCleanerImplTest extends TestCase {
 				return false;
 			}
 		};
-		// Configure the cleaner to wait for 30 seconds between sweeps
-		DatabaseCleanerImpl cleaner =
-			new DatabaseCleanerImpl(callback, 30 * 1000);
+		DatabaseCleanerImpl cleaner = new DatabaseCleanerImpl();
 		long start = System.currentTimeMillis();
 		// Start the cleaner and check that shouldCheckFreeSpace() is called
-		cleaner.startCleaning();
+		cleaner.startCleaning(callback, 30L * 1000L);
 		assertTrue(latch.await(5, TimeUnit.SECONDS));
 		// Stop the cleaner (it should be waiting between sweeps)
 		cleaner.stopCleaning();
 		long end = System.currentTimeMillis();
 		// Check that much less than 30 seconds expired
-		assertTrue(end - start < 10 * 1000);
+		assertTrue(end - start < 10L * 1000L);
 	}
 }
diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java
index 4ebfe4c726b79b9b1d20fc98c880906eb2b9a332..878b8a05a92e28ad2337f28dc65b44d2b5db9d10 100644
--- a/test/net/sf/briar/db/DatabaseComponentTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentTest.java
@@ -96,7 +96,9 @@ public abstract class DatabaseComponentTest extends TestCase {
 			allowing(database).commitTransaction(txn);
 			// open(false)
 			oneOf(database).open(false);
-			oneOf(cleaner).startCleaning();
+			oneOf(cleaner).startCleaning(
+					with(any(DatabaseCleaner.Callback.class)),
+					with(any(long.class)));
 			// getRating(authorId)
 			oneOf(database).getRating(txn, authorId);
 			will(returnValue(Rating.UNRATED));