diff --git a/src/main/java/de/thm/arsnova/config/PersistanceConfig.java b/src/main/java/de/thm/arsnova/config/PersistanceConfig.java
index 13d31dc60d9450547019904e4e337ed2c1dc3977..6c81d4956c5c48ffd2986cfdeff2d187e3078668 100644
--- a/src/main/java/de/thm/arsnova/config/PersistanceConfig.java
+++ b/src/main/java/de/thm/arsnova/config/PersistanceConfig.java
@@ -19,6 +19,8 @@ import org.springframework.context.annotation.Profile;
 @Configuration
 @Profile("!test")
 public class PersistanceConfig {
+	private static final int MIGRATION_SOCKET_TIMEOUT = 30000;
+
 	@Value("${couchdb.name}") private String couchDbName;
 	@Value("${couchdb.host}") private String couchDbHost;
 	@Value("${couchdb.port}") private int couchDbPort;
@@ -45,6 +47,11 @@ public class PersistanceConfig {
 		return new StdCouchDbInstance(couchDbHttpClientFactory().getObject());
 	}
 
+	@Bean
+	public StdCouchDbInstance couchDbMigrationInstance() throws Exception {
+		return new StdCouchDbInstance(couchDbMigrationHttpClientFactory().getObject());
+	}
+
 	@Bean
 	public HttpClientFactoryBean couchDbHttpClientFactory() throws Exception {
 		final HttpClientFactoryBean factory = new HttpClientFactoryBean();
@@ -58,6 +65,14 @@ public class PersistanceConfig {
 		return factory;
 	}
 
+	@Bean
+	public HttpClientFactoryBean couchDbMigrationHttpClientFactory() throws Exception {
+		final HttpClientFactoryBean factory = couchDbHttpClientFactory();
+		factory.setSocketTimeout(MIGRATION_SOCKET_TIMEOUT);
+
+		return factory;
+	}
+
 	@Bean
 	public CouchDbObjectMapperFactory couchDbObjectMapperFactory() {
 		return new CouchDbObjectMapperFactory();
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/migrations/V2ToV3Migration.java b/src/main/java/de/thm/arsnova/persistance/couchdb/migrations/V2ToV3Migration.java
index becca1e06c2d97b3e44111c57d722bec69a5493b..904ddcae5b6b4649116668742bd39fc46bd71b71 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/migrations/V2ToV3Migration.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/migrations/V2ToV3Migration.java
@@ -31,6 +31,7 @@ import de.thm.arsnova.persistance.ContentRepository;
 import de.thm.arsnova.persistance.RoomRepository;
 import de.thm.arsnova.persistance.UserRepository;
 import de.thm.arsnova.persistance.couchdb.support.MangoCouchDbConnector;
+import org.ektorp.DbAccessException;
 import org.ektorp.DocumentNotFoundException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -97,13 +98,17 @@ public class V2ToV3Migration implements Migration {
 	public void migrate() {
 		createV2Index();
 		migrator.setIgnoreRevision(true);
-		migrateUsers();
-		migrateUnregisteredUsers();
-		migrateRooms();
-		migrateMotds();
-		migrateComments();
-		migrateContents();
-		migrateAnswers();
+		try {
+			migrateUsers();
+			migrateUnregisteredUsers();
+			migrateRooms();
+			migrateMotds();
+			migrateComments();
+			migrateContents();
+			migrateAnswers();
+		} catch (InterruptedException e) {
+			throw new DbAccessException(e);
+		}
 		migrator.setIgnoreRevision(false);
 	}
 
@@ -156,7 +161,18 @@ public class V2ToV3Migration implements Migration {
 		fromConnector.createPartialJsonIndex(MOTDLIST_INDEX, fields, filterSelector);
 	}
 
-	private void migrateUsers() {
+	private void waitForV2Index(final String name) throws InterruptedException {
+		for (int i = 0; i < 10; i++) {
+			if (fromConnector.initializeIndex(name)) {
+				return;
+			}
+			Thread.sleep(10000 * Math.round(1.0 + 0.5 * i));
+		}
+	}
+
+	private void migrateUsers() throws InterruptedException {
+		waitForV2Index(USER_INDEX);
+		waitForV2Index(LOGGEDIN_INDEX);
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "userdetails");
 		MangoCouchDbConnector.MangoQuery query = new MangoCouchDbConnector.MangoQuery(queryOptions);
@@ -189,7 +205,9 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private void migrateUnregisteredUsers() {
+	private void migrateUnregisteredUsers() throws InterruptedException {
+		waitForV2Index(USER_INDEX);
+		waitForV2Index(LOGGEDIN_INDEX);
 		/* Load registered usernames to exclude them later */
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "userdetails");
@@ -232,7 +250,8 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private void migrateRooms() {
+	private void migrateRooms() throws InterruptedException {
+		waitForV2Index(SESSION_INDEX);
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "session");
 		MangoCouchDbConnector.MangoQuery query = new MangoCouchDbConnector.MangoQuery(queryOptions);
@@ -262,7 +281,8 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private void migrateMotds() {
+	private void migrateMotds() throws InterruptedException {
+		waitForV2Index(MOTD_INDEX);
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "motd");
 		/* Exclude outdated MotDs */
@@ -300,7 +320,8 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private void migrateComments() {
+	private void migrateComments() throws InterruptedException {
+		waitForV2Index(FULL_INDEX_BY_TYPE);
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "interposed_question");
 		MangoCouchDbConnector.MangoQuery query = new MangoCouchDbConnector.MangoQuery(queryOptions);
@@ -343,7 +364,8 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private void migrateContents() {
+	private void migrateContents() throws InterruptedException {
+		waitForV2Index(FULL_INDEX_BY_TYPE);
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "skill_question");
 		MangoCouchDbConnector.MangoQuery query = new MangoCouchDbConnector.MangoQuery(queryOptions);
@@ -376,7 +398,8 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private void migrateAnswers() {
+	private void migrateAnswers() throws InterruptedException {
+		waitForV2Index(FULL_INDEX_BY_TYPE);
 		Map<String, Object> queryOptions = new HashMap<>();
 		queryOptions.put("type", "skill_question_answer");
 		MangoCouchDbConnector.MangoQuery query = new MangoCouchDbConnector.MangoQuery(queryOptions);
@@ -414,10 +437,11 @@ public class V2ToV3Migration implements Migration {
 		}
 	}
 
-	private HashSet<String> migrateMotdIds(final Set<String> oldIds) {
+	private HashSet<String> migrateMotdIds(final Set<String> oldIds) throws InterruptedException {
 		if (oldIds.isEmpty()) {
 			return new HashSet<>();
 		}
+		waitForV2Index(MOTD_INDEX);
 		Map<String, Object> queryOptions = new HashMap<>();
 		Map<String, Set<String>> subQuery1 = new HashMap<>();
 		subQuery1.put("$in", oldIds);
@@ -434,7 +458,8 @@ public class V2ToV3Migration implements Migration {
 		return new HashSet<>(fromConnector.query(query, "_id", String.class));
 	}
 
-	private MotdList loadMotdList(final String username) {
+	private MotdList loadMotdList(final String username) throws InterruptedException {
+		waitForV2Index(MOTDLIST_INDEX);
 		HashMap<String, Object> motdListQueryOptions = new HashMap<>();
 		motdListQueryOptions.put("type", "motdlist");
 		motdListQueryOptions.put("username", username);
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/support/MangoCouchDbConnector.java b/src/main/java/de/thm/arsnova/persistance/couchdb/support/MangoCouchDbConnector.java
index 15239844b939d7e3d91c8decf76f9b1d640a4828..2155757b5686339509d9a02c498e93a2455bd3f8 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/support/MangoCouchDbConnector.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/support/MangoCouchDbConnector.java
@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.util.Converter;
 import de.thm.arsnova.entities.serialization.View;
 import org.ektorp.CouchDbInstance;
 import org.ektorp.DbAccessException;
+import org.ektorp.http.HttpResponse;
 import org.ektorp.impl.ObjectMapperFactory;
 import org.ektorp.impl.StdCouchDbConnector;
 import org.slf4j.Logger;
@@ -19,6 +20,7 @@ import org.slf4j.LoggerFactory;
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -102,6 +104,7 @@ public class MangoCouchDbConnector extends StdCouchDbConnector {
 			this.selector = selector;
 		}
 
+		@JsonInclude(JsonInclude.Include.ALWAYS)
 		@JsonView(View.Persistence.class)
 		public Map<String, ?> getSelector() {
 			return selector;
@@ -271,4 +274,23 @@ public class MangoCouchDbConnector extends StdCouchDbConnector {
 	public void createJsonIndex(final String name, final List<MangoQuery.Sort> fields) {
 		createPartialJsonIndex(name, fields, null);
 	}
+
+	public boolean initializeIndex(final String name) {
+		MangoQuery query = new MangoQuery(Collections.EMPTY_MAP);
+		query.setIndexDocument(name);
+		query.setLimit(0);
+		try {
+			String queryString = objectMapper.writeValueAsString(query);
+			logger.debug("Using Mango API query to initialize CouchDB index: {}", queryString);
+			HttpResponse response = restTemplate.postUncached(dbURI.append("_find").toString(), queryString);
+			response.releaseConnection();
+		} catch (JsonProcessingException e) {
+			throw new DbAccessException("Could not serialize Mango query.");
+		} catch (DbAccessException e) {
+			logger.debug("CouchDB index is not ready yet: {}", name, e);
+			return false;
+		}
+
+		return true;
+	}
 }