diff --git a/pom.xml b/pom.xml
index 6d8ae36acc222f7d42dede0340d52010edb36268..9298671601f1680f1781e344ae054e0a0f6a5874 100644
--- a/pom.xml
+++ b/pom.xml
@@ -219,6 +219,18 @@
 			<groupId>org.springframework.security</groupId>
 			<artifactId>spring-security-ldap</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-actuator-autoconfigure</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.micrometer</groupId>
+			<artifactId>micrometer-registry-jmx</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.micrometer</groupId>
+			<artifactId>micrometer-registry-prometheus</artifactId>
+		</dependency>
 		<dependency>
 			<groupId>org.hibernate.validator</groupId>
 			<artifactId>hibernate-validator</artifactId>
@@ -395,11 +407,6 @@
 			<artifactId>swagger-annotations</artifactId>
 			<version>1.5.22</version>
 		</dependency>
-		<dependency>
-			<groupId>com.codahale.metrics</groupId>
-			<artifactId>metrics-annotation</artifactId>
-			<version>3.0.2</version>
-		</dependency>
 		<dependency>
 			<groupId>org.checkerframework</groupId>
 			<artifactId>checker-qual</artifactId>
@@ -441,6 +448,12 @@
 					<source>1.8</source>
 					<target>1.8</target>
 					<aspectLibraries>
+						<!-- Disabled for now, see https://github.com/micrometer-metrics/micrometer/issues/1149.
+						<aspectLibrary>
+							<groupId>io.micrometer</groupId>
+							<artifactId>micrometer-core</artifactId>
+						</aspectLibrary>
+						-->
 						<aspectLibrary>
 							<groupId>org.springframework</groupId>
 							<artifactId>spring-aspects</artifactId>
diff --git a/src/main/java/de/thm/arsnova/config/AppConfig.java b/src/main/java/de/thm/arsnova/config/AppConfig.java
index 4b14d85ad2a24aa00fc7bc7aec8c15289ed2fb04..1e992cb6dfbec9909b35417a56a4646f5b2ad3e6 100644
--- a/src/main/java/de/thm/arsnova/config/AppConfig.java
+++ b/src/main/java/de/thm/arsnova/config/AppConfig.java
@@ -21,11 +21,20 @@ package de.thm.arsnova.config;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import io.micrometer.core.instrument.MeterRegistry;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
+import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
+import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
+import org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter;
+import org.springframework.boot.actuate.metrics.web.servlet.WebMvcTagsProvider;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.cache.CacheManager;
 import org.springframework.cache.annotation.EnableCaching;
@@ -69,7 +78,7 @@ import de.thm.arsnova.util.ImageUtils;
 import de.thm.arsnova.web.CacheControlInterceptorHandler;
 import de.thm.arsnova.web.CorsFilter;
 import de.thm.arsnova.web.DeprecatedApiInterceptorHandler;
-import de.thm.arsnova.web.PathApiVersionContentNegotiationStrategy;
+import de.thm.arsnova.web.PathBasedContentNegotiationStrategy;
 import de.thm.arsnova.web.ResponseInterceptorHandler;
 import de.thm.arsnova.websocket.ArsnovaSocketioServer;
 import de.thm.arsnova.websocket.ArsnovaSocketioServerImpl;
@@ -87,18 +96,25 @@ import de.thm.arsnova.websocket.ArsnovaSocketioServerImpl;
 		"de.thm.arsnova.cache",
 		"de.thm.arsnova.controller",
 		"de.thm.arsnova.event",
+		"de.thm.arsnova.management",
 		"de.thm.arsnova.security",
 		"de.thm.arsnova.service",
 		"de.thm.arsnova.web",
 		"de.thm.arsnova.websocket.handler"})
 @Configuration
 @EnableAsync(mode = AdviceMode.ASPECTJ)
+@EnableAutoConfiguration(exclude = {
+		DataSourceAutoConfiguration.class,
+		DataSourceTransactionManagerAutoConfiguration.class})
 @EnableCaching(mode = AdviceMode.ASPECTJ)
 @EnableScheduling
 @EnableSpringConfigured
 @EnableWebMvc
 @PropertySource(
-		value = {"classpath:config/defaults.yml", "file:${arsnova.config-dir:.}/application.yml"},
+		value = {
+			"classpath:config/defaults.yml",
+			"classpath:config/actuator.yml",
+			"file:${arsnova.config-dir:.}/application.yml"},
 		ignoreResourceNotFound = true,
 		encoding = "UTF-8",
 		factory = YamlPropertySourceFactory.class
@@ -109,6 +125,7 @@ public class AppConfig implements WebMvcConfigurer {
 	public static final String API_V3_MEDIA_TYPE_VALUE = "application/vnd.de.thm.arsnova.v3+json";
 	public static final MediaType API_V2_MEDIA_TYPE = MediaType.valueOf(API_V2_MEDIA_TYPE_VALUE);
 	public static final MediaType API_V3_MEDIA_TYPE = MediaType.valueOf(API_V3_MEDIA_TYPE_VALUE);
+	public static final MediaType ACTUATOR_MEDIA_TYPE = MediaType.valueOf(ActuatorMediaType.V2_JSON);
 
 	@Autowired
 	private Environment env;
@@ -119,18 +136,22 @@ public class AppConfig implements WebMvcConfigurer {
 	@Autowired
 	private SecurityProperties securityProperties;
 
+	@Autowired
+	private WebEndpointProperties webEndpointProperties;
+
 	@Override
 	public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
 		converters.add(defaultJsonMessageConverter());
 		converters.add(apiV2JsonMessageConverter());
+		converters.add(managementJsonMessageConverter());
 		converters.add(stringMessageConverter());
 		//converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
 	}
 
 	@Override
 	public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
-		final PathApiVersionContentNegotiationStrategy strategy =
-				new PathApiVersionContentNegotiationStrategy(API_V3_MEDIA_TYPE);
+		final PathBasedContentNegotiationStrategy strategy =
+				new PathBasedContentNegotiationStrategy(API_V3_MEDIA_TYPE, webEndpointProperties.getBasePath());
 		configurer.mediaType("json", MediaType.APPLICATION_JSON_UTF8);
 		configurer.mediaType("xml", MediaType.APPLICATION_XML);
 		configurer.favorParameter(false);
@@ -161,6 +182,15 @@ public class AppConfig implements WebMvcConfigurer {
 		registry.addResourceHandler("swagger.json").addResourceLocations("classpath:/");
 	}
 
+	/* Provides a Spring Framework (non-Boot) compatible Filter. */
+	@Bean
+	public WebMvcMetricsFilter webMvcMetricsFilterOverride(
+			final MeterRegistry registry, final WebMvcTagsProvider tagsProvider) {
+		final MetricsProperties.Web.Server serverProperties = new MetricsProperties.Web.Server();
+		return new WebMvcMetricsFilter(registry, tagsProvider,
+				serverProperties.getRequestsMetricName(), serverProperties.isAutoTimeRequests());
+	}
+
 	@Bean
 	public CacheControlInterceptorHandler cacheControlInterceptorHandler() {
 		return new CacheControlInterceptorHandler();
@@ -228,6 +258,22 @@ public class AppConfig implements WebMvcConfigurer {
 		return converter;
 	}
 
+	@Bean
+	public MappingJackson2HttpMessageConverter managementJsonMessageConverter() {
+		final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
+		builder
+				.indentOutput(systemProperties.getApi().isIndentResponseBody())
+				.simpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
+		final ObjectMapper mapper = builder.build();
+		final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
+		final List<MediaType> mediaTypes = new ArrayList<>();
+		mediaTypes.add(ACTUATOR_MEDIA_TYPE);
+		mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
+		converter.setSupportedMediaTypes(mediaTypes);
+
+		return converter;
+	}
+
 	@Bean
 	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
 		final PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
diff --git a/src/main/java/de/thm/arsnova/config/AppInitializer.java b/src/main/java/de/thm/arsnova/config/AppInitializer.java
index 74e069a743af0bc36b2bebd1e8cd6df9426a6c7b..d1971121822470ca38242df3ed029b9237922407 100644
--- a/src/main/java/de/thm/arsnova/config/AppInitializer.java
+++ b/src/main/java/de/thm/arsnova/config/AppInitializer.java
@@ -50,11 +50,13 @@ public class AppInitializer extends AbstractAnnotationConfigDispatcherServletIni
 	@Override
 	protected Filter[] getServletFilters() {
 		final CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter("UTF-8");
+		final DelegatingFilterProxy webMvcMetricsFilter = new DelegatingFilterProxy("webMvcMetricsFilterOverride");
 		final DelegatingFilterProxy corsFilter = new DelegatingFilterProxy("corsFilter");
 		final DelegatingFilterProxy maintenanceModeFilter = new DelegatingFilterProxy("maintenanceModeFilter");
 		final DelegatingFilterProxy v2ContentTypeOverrideFilter = new DelegatingFilterProxy("v2ContentTypeOverrideFilter");
 
 		return new Filter[] {
+				webMvcMetricsFilter,
 				characterEncodingFilter,
 				corsFilter,
 				maintenanceModeFilter,
diff --git a/src/main/java/de/thm/arsnova/config/SecurityConfig.java b/src/main/java/de/thm/arsnova/config/SecurityConfig.java
index 47a6df2adbd54e873353f5dfefb56804c72683e7..cb327b08e0ae5208230a5d6d3c7c4f530f144100 100644
--- a/src/main/java/de/thm/arsnova/config/SecurityConfig.java
+++ b/src/main/java/de/thm/arsnova/config/SecurityConfig.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import javax.annotation.PostConstruct;
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletResponse;
 import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
 import org.pac4j.core.client.Client;
 import org.pac4j.core.config.Config;
@@ -32,15 +33,21 @@ import org.pac4j.oidc.client.OidcClient;
 import org.pac4j.oidc.config.OidcConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.AdviceMode;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Profile;
 import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.ldap.core.support.LdapContextSource;
 import org.springframework.security.access.intercept.RunAsManager;
 import org.springframework.security.access.intercept.RunAsManagerImpl;
@@ -71,7 +78,7 @@ import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
 import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
 import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
 import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
+import org.springframework.security.web.access.AccessDeniedHandler;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.logout.LogoutFilter;
 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
@@ -82,6 +89,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import de.thm.arsnova.config.properties.AuthenticationProviderProperties;
 import de.thm.arsnova.config.properties.SecurityProperties;
 import de.thm.arsnova.config.properties.SystemProperties;
+import de.thm.arsnova.controller.ControllerExceptionHelper;
 import de.thm.arsnova.security.CasLogoutSuccessHandler;
 import de.thm.arsnova.security.CasUserDetailsService;
 import de.thm.arsnova.security.CustomLdapUserDetailsMapper;
@@ -126,9 +134,20 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 	}
 
 	public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
+		protected AuthenticationEntryPoint authenticationEntryPoint;
+		protected AccessDeniedHandler accessDeniedHandler;
+
+		public HttpSecurityConfig(final AuthenticationEntryPoint authenticationEntryPoint,
+				final AccessDeniedHandler accessDeniedHandler) {
+			this.authenticationEntryPoint = authenticationEntryPoint;
+			this.accessDeniedHandler = accessDeniedHandler;
+		}
+
 		@Override
 		protected void configure(final HttpSecurity http) throws Exception {
-			http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint());
+			http.exceptionHandling()
+					.authenticationEntryPoint(authenticationEntryPoint)
+					.accessDeniedHandler(accessDeniedHandler);
 			http.csrf().disable();
 			http.headers().addHeaderWriter(new HstsHeaderWriter(false));
 
@@ -149,6 +168,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 	@Order(2)
 	@Profile("!test")
 	public class StatelessHttpSecurityConfig extends HttpSecurityConfig {
+		public StatelessHttpSecurityConfig(
+				@Qualifier("restAuthenticationEntryPoint") final AuthenticationEntryPoint authenticationEntryPoint,
+				final AccessDeniedHandler accessDeniedHandler) {
+			super(authenticationEntryPoint, accessDeniedHandler);
+		}
+
 		@Override
 		protected void configure(final HttpSecurity http) throws Exception {
 			super.configure(http);
@@ -161,6 +186,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 	@Order(1)
 	@Profile("!test")
 	public class StatefulHttpSecurityConfig extends HttpSecurityConfig {
+		public StatefulHttpSecurityConfig(
+				@Qualifier("restAuthenticationEntryPoint") final AuthenticationEntryPoint authenticationEntryPoint,
+				final AccessDeniedHandler accessDeniedHandler) {
+			super(authenticationEntryPoint, accessDeniedHandler);
+		}
+
 		@Override
 		protected void configure(final HttpSecurity http) throws Exception {
 			super.configure(http);
@@ -169,6 +200,29 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 		}
 	}
 
+	@Configuration
+	@Order(Ordered.HIGHEST_PRECEDENCE)
+	@Profile("!test")
+	public class ManagementHttpSecurityConfig extends HttpSecurityConfig {
+		private final String managementPath;
+
+		public ManagementHttpSecurityConfig(
+				@Qualifier("restAuthenticationEntryPoint") final AuthenticationEntryPoint authenticationEntryPoint,
+				final AccessDeniedHandler accessDeniedHandler,
+				final WebEndpointProperties webEndpointProperties) {
+			super(authenticationEntryPoint, accessDeniedHandler);
+			this.managementPath = webEndpointProperties.getBasePath();
+		}
+
+		@Override
+		protected void configure(final HttpSecurity http) throws Exception {
+			super.configure(http);
+			http.antMatcher(managementPath + "/**");
+			http.authorizeRequests().anyRequest().hasRole("ADMIN");
+			http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+		}
+	}
+
 	@Configuration
 	@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, prePostEnabled = true, securedEnabled = true)
 	public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@@ -247,8 +301,29 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 	}
 
 	@Bean
-	public static AuthenticationEntryPoint restAuthenticationEntryPoint() {
-		return new Http403ForbiddenEntryPoint();
+	public static AuthenticationEntryPoint restAuthenticationEntryPoint(
+			@Qualifier("defaultJsonMessageConverter")
+			final MappingJackson2HttpMessageConverter jackson2HttpMessageConverter,
+			final ControllerExceptionHelper controllerExceptionHelper) {
+		return (request, response, accessDeniedException) -> {
+			response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+			response.setContentType(MediaType.APPLICATION_JSON_UTF8.toString());
+			response.getWriter().write(jackson2HttpMessageConverter.getObjectMapper().writeValueAsString(
+					controllerExceptionHelper.handleException(accessDeniedException, Level.DEBUG)));
+		};
+	}
+
+	@Bean
+	public AccessDeniedHandler customAccessDeniedHandler(
+			@Qualifier("defaultJsonMessageConverter")
+			final MappingJackson2HttpMessageConverter jackson2HttpMessageConverter,
+			final ControllerExceptionHelper controllerExceptionHelper) {
+		return (request, response, accessDeniedException) -> {
+			response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+			response.setContentType(MediaType.APPLICATION_JSON_UTF8.toString());
+			response.getWriter().write(jackson2HttpMessageConverter.getObjectMapper().writeValueAsString(
+					controllerExceptionHelper.handleException(accessDeniedException, Level.DEBUG)));
+		};
 	}
 
 	@Bean
diff --git a/src/main/java/de/thm/arsnova/controller/ControllerExceptionHelper.java b/src/main/java/de/thm/arsnova/controller/ControllerExceptionHelper.java
index 27d90282cbfcd8a84831026d75a55e32aef16c36..82cca7351522fa4b9ee213dc8e00a19c4950c06f 100644
--- a/src/main/java/de/thm/arsnova/controller/ControllerExceptionHelper.java
+++ b/src/main/java/de/thm/arsnova/controller/ControllerExceptionHelper.java
@@ -39,7 +39,7 @@ public class ControllerExceptionHelper {
 		this.exposeMessages = systemProperties.getApi().isExposeErrorMessages();
 	}
 
-	protected Map<String, Object> handleException(@NonNull final Throwable e, @NonNull final Level level) {
+	public Map<String, Object> handleException(@NonNull final Throwable e, @NonNull final Level level) {
 		final String message = e.getMessage() != null ? e.getMessage() : "";
 		log(level, message, e);
 		final Map<String, Object> result = new HashMap<>();
diff --git a/src/main/java/de/thm/arsnova/controller/WelcomeController.java b/src/main/java/de/thm/arsnova/controller/WelcomeController.java
index 8ce005e5084572e210ef09a8a299c45576ef8296..59c32288119caecd187a47e055c4675149899207 100644
--- a/src/main/java/de/thm/arsnova/controller/WelcomeController.java
+++ b/src/main/java/de/thm/arsnova/controller/WelcomeController.java
@@ -22,11 +22,9 @@ import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.UnknownHostException;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
-import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
@@ -42,6 +40,7 @@ import org.springframework.web.client.RestTemplate;
 import org.springframework.web.servlet.View;
 import org.springframework.web.servlet.view.RedirectView;
 
+import de.thm.arsnova.management.VersionInfoContributor;
 import de.thm.arsnova.web.exceptions.BadRequestException;
 import de.thm.arsnova.web.exceptions.NoContentException;
 
@@ -54,8 +53,8 @@ public class WelcomeController extends AbstractController {
 	@Value("${mobile.path}")
 	private String mobileContextPath;
 
-	@Resource(name = "versionInfoProperties")
-	private Properties versionInfoProperties;
+	@Autowired
+	private VersionInfoContributor versionInfoContributor;
 
 	@RequestMapping(value = "/", method = RequestMethod.GET)
 	public View home() {
@@ -65,18 +64,7 @@ public class WelcomeController extends AbstractController {
 	@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/json")
 	@ResponseBody
 	public Map<String, Object> jsonHome() {
-		final Map<String, Object> response = new HashMap<>();
-		final Map<String, Object> version = new HashMap<>();
-
-		version.put("string", versionInfoProperties.getProperty("version.string"));
-		version.put("buildTime", versionInfoProperties.getProperty("version.build-time"));
-		version.put("gitCommitId", versionInfoProperties.getProperty("version.git.commit-id"));
-		version.put("gitDirty", Boolean.parseBoolean(versionInfoProperties.getProperty("version.git.dirty")));
-
-		response.put("productName", "arsnova-backend");
-		response.put("version", version);
-
-		return response;
+		return versionInfoContributor.getInfoDetails();
 	}
 
 	@RequestMapping(value = "/checkframeoptionsheader", method = RequestMethod.POST)
diff --git a/src/main/java/de/thm/arsnova/management/StatisticsEndpoint.java b/src/main/java/de/thm/arsnova/management/StatisticsEndpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..084972f475cf31a10f1674bb8f29565c64c82a15
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/management/StatisticsEndpoint.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2019 The ARSnova Team and Contributors
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.thm.arsnova.management;
+
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+import org.springframework.stereotype.Component;
+
+import de.thm.arsnova.model.Statistics;
+import de.thm.arsnova.service.StatisticsService;
+
+@Component
+@Endpoint(id = "stats")
+public class StatisticsEndpoint {
+	private StatisticsService statisticsService;
+
+	public StatisticsEndpoint(final StatisticsService statisticsService) {
+		this.statisticsService = statisticsService;
+	}
+
+	@ReadOperation
+	public Statistics readStatistics() {
+		return statisticsService.getStatistics();
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/management/VersionInfoContributor.java b/src/main/java/de/thm/arsnova/management/VersionInfoContributor.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a7defe350b7386095dc4461203dbcf8baa53e09
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/management/VersionInfoContributor.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of ARSnova Backend.
+ * Copyright (C) 2012-2019 The ARSnova Team and Contributors
+ *
+ * ARSnova Backend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova Backend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.thm.arsnova.management;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import javax.annotation.Resource;
+import org.springframework.boot.actuate.info.Info;
+import org.springframework.boot.actuate.info.InfoContributor;
+import org.springframework.stereotype.Component;
+
+@Component
+public class VersionInfoContributor implements InfoContributor {
+	private Map<String, Object> infoDetails;
+
+	@Override
+	public void contribute(final Info.Builder builder) {
+		builder.withDetails(infoDetails);
+	}
+
+	@Resource(name = "versionInfoProperties")
+	public void setVersionInfoProperties(final Properties versionInfoProperties) {
+		infoDetails = new HashMap<>();
+		final Map<String, Object> version = new HashMap<>();
+
+		version.put("string", versionInfoProperties.getProperty("version.string"));
+		version.put("buildTime", versionInfoProperties.getProperty("version.build-time"));
+		version.put("gitCommitId", versionInfoProperties.getProperty("version.git.commit-id"));
+		version.put("gitDirty", Boolean.parseBoolean(versionInfoProperties.getProperty("version.git.dirty")));
+
+		infoDetails.put("productName", "arsnova-backend");
+		infoDetails.put("version", version);
+	}
+
+	public Map<String, Object> getInfoDetails() {
+		return infoDetails;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/service/UserServiceImpl.java b/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
index 48ed77f620132206fcb7d64e94a08e18f1419e04..9c399600660ef1fa1f39fe7f77bde2bd2878a4e0 100644
--- a/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/service/UserServiceImpl.java
@@ -18,7 +18,6 @@
 
 package de.thm.arsnova.service;
 
-import com.codahale.metrics.annotation.Gauge;
 import java.io.IOException;
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -66,7 +65,6 @@ import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.Validator;
 import org.springframework.web.util.UriUtils;
-import org.stagemonitor.core.metrics.MonitorGauges;
 
 import de.thm.arsnova.config.properties.AuthenticationProviderProperties;
 import de.thm.arsnova.config.properties.SecurityProperties;
@@ -87,7 +85,6 @@ import de.thm.arsnova.web.exceptions.UnauthorizedException;
  * Performs all user related operations.
  */
 @Service
-@MonitorGauges
 public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> implements UserService {
 
 	private static final int LOGIN_TRY_RESET_DELAY_MS = 30 * 1000;
@@ -324,7 +321,6 @@ public class UserServiceImpl extends DefaultEntityServiceImpl<UserProfile> imple
 	}
 
 	@Override
-	@Gauge
 	public int loggedInUsers() {
 		return userIdToRoomId.size();
 	}
diff --git a/src/main/java/de/thm/arsnova/web/PathApiVersionContentNegotiationStrategy.java b/src/main/java/de/thm/arsnova/web/PathBasedContentNegotiationStrategy.java
similarity index 82%
rename from src/main/java/de/thm/arsnova/web/PathApiVersionContentNegotiationStrategy.java
rename to src/main/java/de/thm/arsnova/web/PathBasedContentNegotiationStrategy.java
index b5875482a84979586104c51d2253d3825f793882..a7e7dd5869fccce322fb8665898ae92ae7e24fa0 100644
--- a/src/main/java/de/thm/arsnova/web/PathApiVersionContentNegotiationStrategy.java
+++ b/src/main/java/de/thm/arsnova/web/PathBasedContentNegotiationStrategy.java
@@ -39,14 +39,17 @@ import de.thm.arsnova.controller.AbstractEntityController;
  *
  * @author Daniel Gerhardt
  */
-public class PathApiVersionContentNegotiationStrategy implements ContentNegotiationStrategy {
-	private static final Logger logger = LoggerFactory.getLogger(PathApiVersionContentNegotiationStrategy.class);
+public class PathBasedContentNegotiationStrategy implements ContentNegotiationStrategy {
+	private static final Logger logger = LoggerFactory.getLogger(PathBasedContentNegotiationStrategy.class);
+
+	private final String managementPath;
 
 	private MediaType fallback;
 	private MediaType empty = MediaType.valueOf(AbstractEntityController.MEDIATYPE_EMPTY);
 
-	public PathApiVersionContentNegotiationStrategy(final MediaType fallback) {
+	public PathBasedContentNegotiationStrategy(final MediaType fallback, final String managementPath) {
 		this.fallback = fallback;
+		this.managementPath = managementPath + "/";
 	}
 
 	@Override
@@ -54,7 +57,11 @@ public class PathApiVersionContentNegotiationStrategy implements ContentNegotiat
 			throws HttpMediaTypeNotAcceptableException {
 		final HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
 		final List<MediaType> mediaTypes = new ArrayList<>();
-		if (servletRequest.getServletPath().startsWith("/v2/")) {
+		if (servletRequest.getServletPath().startsWith(managementPath)) {
+			logger.trace("Negotiating content based on path for management API");
+			mediaTypes.add(AppConfig.ACTUATOR_MEDIA_TYPE);
+			mediaTypes.add(MediaType.TEXT_PLAIN);
+		} else if (servletRequest.getServletPath().startsWith("/v2/")) {
 			logger.trace("Negotiating content based on path for API v2");
 			mediaTypes.add(AppConfig.API_V2_MEDIA_TYPE);
 			mediaTypes.add(MediaType.TEXT_PLAIN);
diff --git a/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java b/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java
index 4717df44f9683b4b0e45e25702e09e5346ecf3ad..d74a42f50d02de163b99d8ee7ec7dd08b7242949 100644
--- a/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java
+++ b/src/main/java/de/thm/arsnova/websocket/ArsnovaSocketioServerImpl.java
@@ -18,7 +18,6 @@
 
 package de.thm.arsnova.websocket;
 
-import com.codahale.metrics.annotation.Timed;
 import com.corundumstudio.socketio.AckRequest;
 import com.corundumstudio.socketio.Configuration;
 import com.corundumstudio.socketio.SocketConfig;
@@ -29,6 +28,7 @@ import com.corundumstudio.socketio.listener.DataListener;
 import com.corundumstudio.socketio.listener.DisconnectListener;
 import com.corundumstudio.socketio.protocol.Packet;
 import com.corundumstudio.socketio.protocol.PacketType;
+import io.micrometer.core.annotation.Timed;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -153,7 +153,7 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer {
 
 		server.addEventListener("setFeedback", Feedback.class, new DataListener<Feedback>() {
 			@Override
-			@Timed(name = "setFeedbackEvent.onData")
+			@Timed("setFeedbackEvent.onData")
 			public void onData(final SocketIOClient client, final Feedback data, final AckRequest ackSender) {
 				final String userId = userService.getUserIdToSocketId(client.getSessionId());
 				if (userId == null) {
@@ -177,7 +177,7 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer {
 
 		server.addEventListener("setSession", Room.class, new DataListener<Room>() {
 			@Override
-			@Timed(name = "setSessionEvent.onData")
+			@Timed("setSessionEvent.onData")
 			public void onData(final SocketIOClient client, final Room room, final AckRequest ackSender) {
 				final String userId = userService.getUserIdToSocketId(client.getSessionId());
 				if (null == userId) {
@@ -211,7 +211,7 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer {
 				Comment.class,
 				new DataListener<Comment>() {
 					@Override
-					@Timed(name = "readInterposedQuestionEvent.onData")
+					@Timed("readInterposedQuestionEvent.onData")
 					public void onData(
 							final SocketIOClient client,
 							final Comment comment,
@@ -244,7 +244,7 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer {
 				ScoreOptions.class,
 				new DataListener<ScoreOptions>() {
 					@Override
-					@Timed(name = "setLearningProgressOptionsEvent.onData")
+					@Timed("setLearningProgressOptionsEvent.onData")
 					public void onData(
 							final SocketIOClient client, final ScoreOptions scoreOptions, final AckRequest ack) {
 						throw new UnsupportedOperationException("Not implemented.");
@@ -254,7 +254,7 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer {
 
 		server.addConnectListener(new ConnectListener() {
 			@Override
-			@Timed
+			@Timed("onConnect")
 			public void onConnect(final SocketIOClient client) {
 
 			}
@@ -262,7 +262,7 @@ public class ArsnovaSocketioServerImpl implements ArsnovaSocketioServer {
 
 		server.addDisconnectListener(new DisconnectListener() {
 			@Override
-			@Timed
+			@Timed("onDisconnect")
 			public void onDisconnect(final SocketIOClient client) {
 				if (
 						userService == null
diff --git a/src/main/java/org/stagemonitor/core/metrics/MonitorGauges.java b/src/main/java/org/stagemonitor/core/metrics/MonitorGauges.java
deleted file mode 100644
index 4e1da49e4e0cb5a9446d958ecc8c6621bc8a1330..0000000000000000000000000000000000000000
--- a/src/main/java/org/stagemonitor/core/metrics/MonitorGauges.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.stagemonitor.core.metrics;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * When a type is marked with this annotation, the creation of gauges with
- * {@link com.codahale.metrics.annotation.Gauge} is activated for that type.
- *
- * <pre><code>
- *     \@MonitorGauges
- *     public class Queue {
- *         \@Gauge(name = "queueSize")
- *         public int getQueueSize() {
- *             return queue.size;
- *         }
- *     }
- * </code></pre>
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface MonitorGauges {
-}
diff --git a/src/main/resources/META-INF/aop.xml b/src/main/resources/META-INF/aop.xml
index fe4871b30ed1a8777f4caccb3c138cc8747a843c..9887fa3ffc05ec45fa30845d1bf7576defd76c93 100644
--- a/src/main/resources/META-INF/aop.xml
+++ b/src/main/resources/META-INF/aop.xml
@@ -9,5 +9,9 @@
 		<aspect name="de.thm.arsnova.web.RangeAspect"/>
 		<aspect name="de.thm.arsnova.web.InternalEntityAspect"/>
 		<aspect name="de.thm.arsnova.websocket.WebsocketAuthenticationAspect"/>
+		<!-- Micrometer does not have a aop.xml config for its aspects. -->
+		<!-- Disabled for now, see https://github.com/micrometer-metrics/micrometer/issues/1149.
+		<aspect name="io.micrometer.core.aop.TimedAspect"/>
+		-->
 	</aspects>
 </aspectj>
diff --git a/src/main/resources/config/actuator.yml b/src/main/resources/config/actuator.yml
new file mode 100644
index 0000000000000000000000000000000000000000..568e51f7ff1ea79de1f20d6a69ddeb17de4e0fdd
--- /dev/null
+++ b/src/main/resources/config/actuator.yml
@@ -0,0 +1,11 @@
+arsnova:
+  management:
+    endpoints:
+      web:
+        base-path: /management
+        exposure:
+          include: "*"
+    metrics:
+      web:
+        server:
+          auto-time-requests: true