diff --git a/src/main/java/de/thm/arsnova/controller/UserController.java b/src/main/java/de/thm/arsnova/controller/UserController.java
index 79d36774b91da28dae006d37f76afb0d8c78de52..e2dd6e1a9df6c6c30e3c14de7630d0cf4642a45f 100644
--- a/src/main/java/de/thm/arsnova/controller/UserController.java
+++ b/src/main/java/de/thm/arsnova/controller/UserController.java
@@ -17,7 +17,10 @@
  */
 package de.thm.arsnova.controller;
 
+import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.DbUser;
+import de.thm.arsnova.entities.LoggedIn;
+import de.thm.arsnova.entities.User;
 import de.thm.arsnova.services.IUserService;
 import de.thm.arsnova.services.UserSessionService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +49,9 @@ public class UserController extends AbstractController {
 	@Autowired
 	private UserSessionService userSessionService;
 
+	@Autowired
+	private IDatabaseDao iDatabaseDao;
+
 	@RequestMapping(value = "/register", method = RequestMethod.POST)
 	public void register(@RequestParam final String username,
 			@RequestParam final String password,
@@ -76,12 +82,16 @@ public class UserController extends AbstractController {
 	}
 
 	@RequestMapping(value = "/{username}/", method = RequestMethod.DELETE)
-	public void activate(
+	public void delete(
 			@PathVariable final String username,
 			final HttpServletRequest request,
 			final HttpServletResponse response) {
-		if (null == userService.deleteDbUser(username)) {
+		LoggedIn loggedIn = iDatabaseDao.getLoggedInByUser(new User(username));
+		if (null == loggedIn) {
 			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+		} else {
+			userService.deleteUserContent(loggedIn);
+			userService.anonymizeUser(loggedIn);
 		}
 	}
 
diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 4028845db1495af16848d84e15d85c19c338ce04..9f59d2ae2b5ca48201d94bc0a9e24181059e92bd 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -826,6 +826,35 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		}
 	}
 
+	@Override
+	public LoggedIn getLoggedInByUser(User user) {
+		final NovaView view = new NovaView("logged_in/all");
+		view.setKey(user.getUsername());
+		view.setIncludeDocs(true);
+		LoggedIn l = null;
+		final ViewResults result = getDatabase().view(view);
+		for (Document doc : result.getResults()) {
+			final MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry();
+			final Morpher dynaMorpher = new BeanMorpher(VisitedSession.class, morpherRegistry);
+			morpherRegistry.registerMorpher(dynaMorpher);
+
+			if (result.getJSONArray("rows").optJSONObject(0) == null) {
+				return null;
+			}
+			l = (LoggedIn) JSONObject.toBean(
+					doc.getJSONObject().getJSONObject("doc"),
+					LoggedIn.class
+			);
+			@SuppressWarnings("unchecked")
+			final Collection<VisitedSession> vs = JSONArray.toCollection(
+					doc.getJSONObject().getJSONObject("doc").getJSONArray("visitedSessions"),
+					VisitedSession.class
+			);
+			l.setVisitedSessions(new ArrayList<>(vs));
+		}
+		return l;
+	}
+
 	@Override
 	@CachePut(value = "sessions")
 	public Session updateSessionOwnerActivity(final Session session) {
@@ -909,6 +938,35 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		getDatabase().deleteDocument(d);
 	}
 
+	@CacheEvict("answers")
+	@Override
+	public List<Answer> getUserAnswersForSession(String username, String sessionId) {
+		final NovaView view = new NovaView("answer/by_user");
+		view.setKey(username, sessionId);
+		view.setIncludeDocs(true);
+
+		List<Answer> answers = new ArrayList<>();
+
+		List<Document> results = this.getDatabase().view(view).getResults();
+
+		final List<List<Document>> partitions = Lists.partition(results, BULK_PARTITION_SIZE);
+		for (List<Document> partition: partitions) {
+			for (Document doc : partition) {
+				if (!"".equals(doc.optString("error"))) {
+					// Skip documents we could not load. Maybe they were deleted.
+					continue;
+				}
+				Answer a = (Answer) JSONObject.toBean(
+						doc.getJSONObject().getJSONObject("doc"),
+						Answer.class
+				);
+				answers.add(a);
+			}
+		}
+
+		return answers;
+	}
+
 	@CacheEvict("answers")
 	@Override
 	public int deleteAnswers(final Question question) {
@@ -986,6 +1044,8 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		}
 	}
 
+
+
 	@Override
 	public List<Answer> getAnswers(final Question question, final int piRound) {
 		final String questionId = question.get_id();
@@ -2234,16 +2294,22 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			questionIds.add(q.get_id());
 			allQuestions.add(d);
 		}
-		final NovaView bulkView = new NovaView("answer/cleanup");
-		bulkView.setKeys(questionIds);
-		bulkView.setIncludeDocs(true);
-		final List<Document> result = getDatabase().view(bulkView).getResults();
 
 		final List<Document> allAnswers = new ArrayList<>();
-		for (Document a : result) {
-			final Document d = new Document(a.getJSONObject("doc"));
-			d.put("_deleted", true);
-			allAnswers.add(d);
+		int resultCounter = 0;
+
+		for (String qId : questionIds) {
+			final NovaView bulkView = new NovaView("answer/cleanup");
+			bulkView.setKey(qId);
+			bulkView.setIncludeDocs(true);
+			final List<Document> result = getDatabase().view(bulkView).getResults();
+
+			for (Document a : result) {
+				final Document d = new Document(a.getJSONObject("doc"));
+				d.put("_deleted", true);
+				allAnswers.add(d);
+			}
+			resultCounter += result.size();
 		}
 
 		try {
@@ -2251,7 +2317,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			deleteList.addAll(allQuestions);
 			getDatabase().bulkSaveDocuments(deleteList.toArray(new Document[deleteList.size()]));
 
-			return new int[] {deleteList.size(), result.size()};
+			return new int[] {deleteList.size(), resultCounter};
 		} catch (IOException e) {
 			logger.error("Could not bulk delete questions and answers.", e);
 		}
@@ -2402,6 +2468,41 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		return 0;
 	}
 
+	@Override
+	public List<LoggedIn> getInactiveLoggedIn(long lastActivityBefore) {
+		final List<LoggedIn> loggedInDocs = new ArrayList<>();
+		NovaView view = new NovaView("logged_in/by_last_activity");
+		view.setEndKey(lastActivityBefore);
+		view.setIncludeDocs(true);
+		final MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry();
+		final Morpher dynaMorpher = new BeanMorpher(VisitedSession.class, morpherRegistry);
+		morpherRegistry.registerMorpher(dynaMorpher);
+		List<Document> results = this.getDatabase().view(view).getResults();
+
+		final List<List<Document>> partitions = Lists.partition(results, BULK_PARTITION_SIZE);
+		for (List<Document> partition: partitions) {
+			for (Document doc : partition) {
+				if (!"".equals(doc.optString("error"))) {
+					// Skip documents we could not load. Maybe they were deleted.
+					continue;
+				}
+				LoggedIn l = (LoggedIn) JSONObject.toBean(
+						doc.getJSONObject().getJSONObject("doc"),
+						LoggedIn.class
+				);
+				@SuppressWarnings("unchecked")
+				final Collection<VisitedSession> vs = JSONArray.toCollection(
+						doc.getJSONObject().getJSONObject("doc").getJSONArray("visitedSessions"),
+						VisitedSession.class
+				);
+				l.setVisitedSessions(new ArrayList<>(vs));
+				loggedInDocs.add(l);
+			}
+		}
+
+		return loggedInDocs;
+	}
+
 	@Override
 	public SessionInfo importSession(User user, ImportExportSession importSession) {
 		final Session session = this.saveSession(user, importSession.generateSessionEntity(user));
@@ -2832,4 +2933,68 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		return null;
 	}
 
+	@Override
+	public void bulkUpdateAnswers(List<Answer> answers) {
+		List<Document> docs = new ArrayList<>();
+		for (Answer a : answers) {
+			if (a.get_id() != null) {
+				final JSONObject json = JSONObject.fromObject(a);
+				docs.add(new Document(json));
+			}
+		}
+		try {
+			getDatabase().bulkSaveDocuments(docs.toArray(new Document[docs.size()]));
+		} catch (IOException e) {
+			logger.error("Could not update Answers document {}.", docs, e);
+		}
+	}
+
+	@Override
+	public void bulkUpdateInterposedQuestion(List<InterposedQuestion> interposedQuestions) {
+		List<Document> docs = new ArrayList<>();
+		for (InterposedQuestion a : interposedQuestions) {
+			if (a.get_id() != null) {
+				final JSONObject json = JSONObject.fromObject(a);
+				docs.add(new Document(json));
+			}
+		}
+		try {
+			getDatabase().bulkSaveDocuments(docs.toArray(new Document[docs.size()]));
+		} catch (IOException e) {
+			logger.error("Could not update interposed question document {}.", docs, e);
+		}
+	}
+
+	@Override
+	public void updateLoggedIn(LoggedIn l) {
+		if (l.get_id() == null) {
+			return;
+		}
+		try {
+			final JSONObject json = JSONObject.fromObject(l);
+			final Document doc = new Document(json);
+			getDatabase().saveDocument(doc);
+		} catch (IOException e) {
+			logger.error("Could not update LoggedIn document {}.", l, e);
+		}
+	}
+
+	@Override
+	public void bulkDeleteInterposedQuestionsForSessionAndUser(String sessionId, String username) {
+		final NovaView view = new NovaView("interposed_question/by_session_and_creator");
+		view.setKey(sessionId, username);
+		final List<Document> result = getDatabase().view(view).getResults();
+		final List<Document> allInterposedQuestions = new ArrayList<>();
+		for (Document a : result) {
+			final Document d = new Document(a.getJSONObject("doc"));
+			d.put("_deleted", true);
+			allInterposedQuestions.add(d);
+		}
+		try {
+			getDatabase().bulkSaveDocuments(allInterposedQuestions.toArray(new Document[allInterposedQuestions.size()]));
+		} catch (IOException e) {
+			logger.error("Could not bulk delete interposed questions.", e);
+		}
+	}
+
 }
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 052957180379141785cd1ada8dbef49a9cb9dd0e..6ad2f30281dc422386b7b523a38ed6f1d59d3675 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -103,6 +103,8 @@ public interface IDatabaseDao {
 
 	LoggedIn registerAsOnlineUser(User u, Session s);
 
+	LoggedIn getLoggedInByUser(User user);
+
 	Session updateSessionOwnerActivity(Session session);
 
 	List<String> getQuestionIds(Session session, User user);
@@ -113,6 +115,8 @@ public interface IDatabaseDao {
 
 	List<String> getUnAnsweredQuestionIds(Session session, User user);
 
+	List<Answer> getUserAnswersForSession(String username, String sessionId);
+
 	Answer getMyAnswer(User me, String questionId, int piRound);
 
 	List<Answer> getAnswers(Question question, int piRound);
@@ -234,6 +238,8 @@ public interface IDatabaseDao {
 
 	int deleteInactiveUsers(long lastActivityBefore);
 
+	List<LoggedIn> getInactiveLoggedIn(long lastActivityBefore);
+
 	CourseScore getLearningProgress(Session session);
 
 	List<SessionInfo> getMySessionsInfo(User user, final int start, final int limit);
@@ -291,4 +297,12 @@ public interface IDatabaseDao {
 	MotdList getMotdListForUser(final String username);
 
 	MotdList createOrUpdateMotdList(MotdList motdlist);
+
+	void bulkUpdateAnswers(List<Answer> answers);
+
+	void bulkUpdateInterposedQuestion(List<InterposedQuestion> interposedQuestions);
+
+	void updateLoggedIn(LoggedIn l);
+
+	void bulkDeleteInterposedQuestionsForSessionAndUser(String sessionId, String username);
 }
diff --git a/src/main/java/de/thm/arsnova/entities/LoggedIn.java b/src/main/java/de/thm/arsnova/entities/LoggedIn.java
index 1ab7caa708467f0518a1941f5babebfd7967960c..153c13d4482a76ac5c90a5850b61851efde8f256 100644
--- a/src/main/java/de/thm/arsnova/entities/LoggedIn.java
+++ b/src/main/java/de/thm/arsnova/entities/LoggedIn.java
@@ -33,6 +33,7 @@ public class LoggedIn {
 	private long timestamp;
 	private List<VisitedSession> visitedSessions = new ArrayList<>();
 	private List<String> _conflicts;
+	private boolean anonymized;
 
 	public LoggedIn() {
 		this.type = "logged_in";
@@ -126,6 +127,14 @@ public class LoggedIn {
 		return !(_conflicts == null || _conflicts.isEmpty());
 	}
 
+	public boolean isAnonymized() {
+		return anonymized;
+	}
+
+	public void setAnonymized(boolean anonymized) {
+		this.anonymized = anonymized;
+	}
+
 	@Override
 	public String toString() {
 		return "LoggedIn [_id=" + _id + ", _rev=" + _rev + ", type=" + type
diff --git a/src/main/java/de/thm/arsnova/entities/User.java b/src/main/java/de/thm/arsnova/entities/User.java
index da31bee08ccb0ecabfc126e63d7638f51c85ab28..18632930d3c8aa7f14551226f963a98f1679c897 100644
--- a/src/main/java/de/thm/arsnova/entities/User.java
+++ b/src/main/java/de/thm/arsnova/entities/User.java
@@ -79,6 +79,11 @@ public class User implements Serializable {
 		setType(LDAP);
 	}
 
+	public User(String username) {
+		setUsername(username);
+		setType(User.ANONYMOUS);
+	}
+
 	public String getUsername() {
 		return username;
 	}
diff --git a/src/main/java/de/thm/arsnova/services/IQuestionService.java b/src/main/java/de/thm/arsnova/services/IQuestionService.java
index 2b04883598eb3ac9d4aa5cb1db1a84a2fc21cea8..ff95d8b42ebb391b2875f126e6f287bc6eade461 100644
--- a/src/main/java/de/thm/arsnova/services/IQuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/IQuestionService.java
@@ -22,6 +22,7 @@ import de.thm.arsnova.entities.InterposedQuestion;
 import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.User;
+import de.thm.arsnova.entities.VisitedSession;
 
 import java.util.List;
 import java.util.Map;
@@ -72,6 +73,8 @@ public interface IQuestionService {
 
 	List<Answer> getFreetextAnswers(String questionId, int offset, int limit);
 
+	List<Answer> getFreetextAnswersInternal(String questionId);
+
 	List<Answer> getMyAnswers(String sessionKey);
 
 	int getTotalAnswerCount(String sessionKey);
@@ -168,4 +171,6 @@ public interface IQuestionService {
 
 	List<Question> replaceImageData(List<Question> questions);
 
+	void anonymizeParticipant(VisitedSession session, String oldUsername, String anonymizedUsername);
+
 }
diff --git a/src/main/java/de/thm/arsnova/services/IUserService.java b/src/main/java/de/thm/arsnova/services/IUserService.java
index 9b90a24fbc221e20b5961c76e3fbdc5e8a7cf988..930f3eb5fc6cc4f2a670c4a038372014cf241056 100644
--- a/src/main/java/de/thm/arsnova/services/IUserService.java
+++ b/src/main/java/de/thm/arsnova/services/IUserService.java
@@ -18,6 +18,7 @@
 package de.thm.arsnova.services;
 
 import de.thm.arsnova.entities.DbUser;
+import de.thm.arsnova.entities.LoggedIn;
 import de.thm.arsnova.entities.User;
 
 import java.util.Map;
@@ -69,4 +70,10 @@ public interface IUserService {
 	void initiatePasswordReset(String username);
 
 	boolean resetPassword(DbUser dbUser, String key, String password);
+
+	void deleteUserContent(LoggedIn user);
+
+	void anonymizeUser(LoggedIn username);
+
+	LoggedIn getLoggedInFromUser(User user);
 }
diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java
index 8d7415b6684af9d543ff81d26c92f80b3ce17782..eb00fc9885d51b09c9219cd272e5cecf51b9a323 100644
--- a/src/main/java/de/thm/arsnova/services/QuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/QuestionService.java
@@ -25,6 +25,7 @@ import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
+import de.thm.arsnova.entities.VisitedSession;
 import de.thm.arsnova.events.*;
 import de.thm.arsnova.exceptions.BadRequestException;
 import de.thm.arsnova.exceptions.ForbiddenException;
@@ -46,6 +47,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.stream.Collectors;
 
 /**
  * Performs all question, interposed question, and answer related operations.
@@ -463,7 +465,6 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 			return databaseDao.getAllAnswers(question);
 		}
 	}
-
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public int getAnswerCount(final String questionId) {
@@ -527,6 +528,17 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 		return answers;
 	}
 
+	@Override
+	@PreAuthorize("isAuthenticated()")
+	public List<Answer> getFreetextAnswersInternal(final String questionId) {
+		final List<Answer> answers = databaseDao.getFreetextAnswers(questionId, 0, 0);
+		if (answers == null) {
+			throw new NotFoundException();
+		}
+
+		return answers;
+	}
+
 	@Override
 	@PreAuthorize("isAuthenticated()")
 	public List<Answer> getMyAnswers(final String sessionKey) {
@@ -1023,4 +1035,35 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis
 
 		return imageData;
 	}
+
+	@Override
+	public void anonymizeParticipant(VisitedSession vs, String oldUsername, String anonymizedUsername) {
+		Session helperSession = new Session();
+		helperSession.set_id(vs.get_id());
+		helperSession.setKeyword(vs.getKeyword());
+		User helperUser = new User(oldUsername);
+
+		List<Answer> answers = new ArrayList<>();
+		List<Answer> questionAnswers = databaseDao.getUserAnswersForSession(oldUsername, vs.get_id());
+		for (Answer a : questionAnswers) {
+			if (a.getUser().equals(oldUsername)) {
+				a.setUser(anonymizedUsername);
+				answers.add(a);
+			}
+		}
+
+		List<InterposedQuestion> comments =
+				databaseDao.getInterposedQuestions(helperSession, helperUser, 0, 0);
+		for (InterposedQuestion c : comments) {
+			c.setCreator(anonymizedUsername);
+			c.setSessionId(vs.get_id());
+		}
+
+		if (!comments.isEmpty()) {
+			databaseDao.bulkUpdateInterposedQuestion(comments);
+		}
+		if (!answers.isEmpty()) {
+			databaseDao.bulkUpdateAnswers(answers);
+		}
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/services/UserService.java b/src/main/java/de/thm/arsnova/services/UserService.java
index 276b0357b1f1bd05c7bafc760294c9c40daec3ac..3b3b5f07240c3a784d6379cd9ee6313ed5ee5bc0 100644
--- a/src/main/java/de/thm/arsnova/services/UserService.java
+++ b/src/main/java/de/thm/arsnova/services/UserService.java
@@ -21,7 +21,11 @@ import com.codahale.metrics.annotation.Gauge;
 import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.DbUser;
 import de.thm.arsnova.entities.User;
+import de.thm.arsnova.entities.LoggedIn;
+import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.entities.VisitedSession;
 import de.thm.arsnova.exceptions.BadRequestException;
+import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
 import org.apache.commons.lang.RandomStringUtils;
@@ -47,6 +51,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.keygen.BytesKeyGenerator;
 import org.springframework.security.crypto.keygen.KeyGenerators;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
@@ -77,6 +82,8 @@ import java.util.regex.Pattern;
 @MonitorGauges
 public class UserService implements IUserService {
 
+	private IQuestionService questionService;
+
 	private static final int LOGIN_TRY_RESET_DELAY_MS = 30 * 1000;
 
 	private static final int LOGIN_BAN_RESET_DELAY_MS = 2 * 60 * 1000;
@@ -88,6 +95,8 @@ public class UserService implements IUserService {
 	private static final long ACTIVATION_KEY_CHECK_INTERVAL_MS = 30 * 60 * 1000L;
 	private static final long ACTIVATION_KEY_DURABILITY_MS = 6 * 60 * 60 * 1000L;
 
+	private static final long USER_INACTIVITY_CHECK_INTERVAL_MS = 30 * 60 * 1000L;
+
 	private static final Logger logger = LoggerFactory.getLogger(UserService.class);
 
 	private static final ConcurrentHashMap<UUID, User> socketid2user = new ConcurrentHashMap<>();
@@ -140,6 +149,9 @@ public class UserService implements IUserService {
 	@Value("${security.admin-accounts}")
 	private String[] adminAccounts;
 
+	@Value("${user.cleanup-days:0}")
+	private int userCleanupThresholdDays;
+
 	private Pattern mailPattern;
 	private BytesKeyGenerator keygen;
 	private BCryptPasswordEncoder encoder;
@@ -151,6 +163,11 @@ public class UserService implements IUserService {
 		loginBans = Collections.synchronizedSet(new HashSet<String>());
 	}
 
+	@Autowired
+	public void setQuestionService(final IQuestionService questionService) {
+		this.questionService = questionService;
+	}
+
 	@Scheduled(fixedDelay = LOGIN_TRY_RESET_DELAY_MS)
 	public void resetLoginTries() {
 		if (!loginTries.isEmpty()) {
@@ -167,14 +184,34 @@ public class UserService implements IUserService {
 		}
 	}
 
+	/*
+	 * This deletes users that did register but not activate their account
+	 */
 	@Scheduled(fixedDelay = ACTIVATION_KEY_CHECK_INTERVAL_MS)
 	public void deleteInactiveUsers() {
-		logger.info("Delete inactive users.");
+		logger.info("Delete not activated users.");
 		long unixTime = System.currentTimeMillis();
 		long lastActivityBefore = unixTime - ACTIVATION_KEY_DURABILITY_MS;
 		databaseDao.deleteInactiveUsers(lastActivityBefore);
 	}
 
+	/*
+	 * This triggers anonymization of users that have been inactive for userCleanupThresholdDays amount of days
+	 */
+	@Scheduled(fixedDelay = USER_INACTIVITY_CHECK_INTERVAL_MS)
+	public void anonymizeInactiveUsers() {
+		if (userCleanupThresholdDays > 0) {
+			logger.info("Anonymize inactive users");
+			long unixTime = System.currentTimeMillis();
+			long lastActivityBefore = unixTime - userCleanupThresholdDays * 24 * 60 * 60 * 1000L;
+			List<LoggedIn> loggedIns = databaseDao.getInactiveLoggedIn(lastActivityBefore);
+			for (LoggedIn l : loggedIns) {
+				deleteUserContent(l);
+				anonymizeUser(l);
+			}
+		}
+	}
+
 	@Override
 	public User getCurrentUser() {
 		final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
@@ -533,6 +570,49 @@ public class UserService implements IUserService {
 		return true;
 	}
 
+	@Override
+	public void deleteUserContent(LoggedIn l) {
+		User user = getCurrentUser();
+		if (!user.isAdmin() && !user.getUsername().equals(l.getUser())) {
+			throw new ForbiddenException();
+		}
+
+		List<Session> userSessions = databaseDao.getSessionsForUsername(l.getUser(), 0, 0);
+		for (Session s : userSessions) {
+			databaseDao.deleteSession(s);
+		}
+	}
+
+	@Override
+	public void anonymizeUser(LoggedIn l) {
+		User user = getCurrentUser();
+		if (!user.isAdmin() && !user.getUsername().equals(l.getUser())) {
+			throw new ForbiddenException();
+		}
+
+		String username = l.getUser();
+		PasswordEncoder pe = new BCryptPasswordEncoder();
+		String anonymizedUsername = pe.encode(username + l.getTimestamp());
+		l.setUser(anonymizedUsername);
+		l.setAnonymized(true);
+		for (VisitedSession vs : l.getVisitedSessions()) {
+			questionService.anonymizeParticipant(vs, username, anonymizedUsername);
+		}
+		// this trims the document because it won't be deleted and stays forever
+		l.setVisitedSessions(new ArrayList<>());
+		DbUser dbUser = this.getDbUser(username);
+		if (dbUser != null) {
+			dbUser.setUsername(anonymizedUsername);
+			databaseDao.createOrUpdateUser(dbUser);
+		}
+		databaseDao.updateLoggedIn(l);
+	}
+
+	@Override
+	public LoggedIn getLoggedInFromUser(User user) {
+		return databaseDao.getLoggedInByUser(user);
+	}
+
 	private void sendEmail(DbUser dbUser, String subject, String body) {
 		MimeMessage msg = mailSender.createMimeMessage();
 		MimeMessageHelper helper = new MimeMessageHelper(msg, "UTF-8");
diff --git a/src/main/resources/arsnova.properties.example b/src/main/resources/arsnova.properties.example
index 34fa9b0a1d80f6a0a91fa1bbd5e3d77c239494e8..93d8c87c988e8e1a121aeb24a1a19ae0e9c697a5 100644
--- a/src/main/resources/arsnova.properties.example
+++ b/src/main/resources/arsnova.properties.example
@@ -246,6 +246,9 @@ session.demo-id=
 # Delete guest sessions automatically after X days of owner inactivity.
 #session.guest-session.cleanup-days=180
 
+# Anonymize user content for users with X days of inactivity
+#user.cleanup-days=180
+
 # Label underneath ARSnova logo
 ui.slogan=Audience Response System
 
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index 0eaf46922750056b7f8881b3e04469b2ee5d564e..6fa3358eaddaf71d4a07999f6da0312205f766bd 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -206,6 +206,12 @@ public class StubDatabaseDao implements IDatabaseDao {
 		return new LoggedIn();
 	}
 
+	@Override
+	public LoggedIn getLoggedInByUser(User user) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
 	@Override
 	public Session updateSessionOwnerActivity(Session session) {
 		// TODO Auto-generated method stub
@@ -754,4 +760,36 @@ public class StubDatabaseDao implements IDatabaseDao {
 		// TODO Auto-generated method stub
 		return null;
 	}
+
+	@Override
+	public void bulkUpdateAnswers(List<Answer> answers) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void updateLoggedIn(LoggedIn l) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void bulkDeleteInterposedQuestionsForSessionAndUser(String sessionId, String username) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public List<LoggedIn> getInactiveLoggedIn(long lastActivityBefore) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public void bulkUpdateInterposedQuestion(List<InterposedQuestion> interposedQuestions) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public List<Answer> getUserAnswersForSession(String username, String sessionId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
 }
diff --git a/src/test/resources/arsnova.properties.example b/src/test/resources/arsnova.properties.example
index 34fa9b0a1d80f6a0a91fa1bbd5e3d77c239494e8..93d8c87c988e8e1a121aeb24a1a19ae0e9c697a5 100644
--- a/src/test/resources/arsnova.properties.example
+++ b/src/test/resources/arsnova.properties.example
@@ -246,6 +246,9 @@ session.demo-id=
 # Delete guest sessions automatically after X days of owner inactivity.
 #session.guest-session.cleanup-days=180
 
+# Anonymize user content for users with X days of inactivity
+#user.cleanup-days=180
+
 # Label underneath ARSnova logo
 ui.slogan=Audience Response System