diff --git a/src/client/app/admin/views/dashboard.queue-charts.vue b/src/client/app/admin/views/dashboard.queue-charts.vue
new file mode 100644
index 0000000000..54b6359156
--- /dev/null
+++ b/src/client/app/admin/views/dashboard.queue-charts.vue
@@ -0,0 +1,185 @@
+<template>
+<div class="mzxlfysy">
+	<div>
+		<header>
+			<span><fa :icon="faInbox"/> In</span>
+			<span v-if="latestStats">{{ latestStats.inbox.activeSincePrevTick | number }} / {{ latestStats.inbox.delayed | number }}</span>
+		</header>
+		<div ref="in"></div>
+	</div>
+	<div>
+		<header>
+			<span><fa :icon="faPaperPlane"/> Out</span>
+			<span v-if="latestStats">{{ latestStats.deliver.activeSincePrevTick | number }} / {{ latestStats.deliver.delayed | number }}</span>
+		</header>
+		<div ref="out"></div>
+	</div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faInbox } from '@fortawesome/free-solid-svg-icons';
+import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
+import ApexCharts from 'apexcharts';
+
+export default Vue.extend({
+	data() {
+		return {
+			stats: [],
+			inChart: null,
+			outChart: null,
+			faInbox, faPaperPlane
+		};
+	},
+
+	computed: {
+		latestStats(): any {
+			return this.stats[this.stats.length - 1];
+		}
+	},
+
+	watch: {
+		stats(stats) {
+			this.inChart.updateSeries([{
+				data: stats.map((x, i) => ({ x: i, y: x.inbox.activeSincePrevTick }))
+			}, {
+				data: stats.map((x, i) => ({ x: i, y: x.inbox.delayed }))
+			}]);
+			this.outChart.updateSeries([{
+				data: stats.map((x, i) => ({ x: i, y: x.deliver.activeSincePrevTick }))
+			}, {
+				data: stats.map((x, i) => ({ x: i, y: x.deliver.delayed }))
+			}]);
+		}
+	},
+
+	mounted() {
+		const chartOpts = {
+			chart: {
+				type: 'area',
+				height: 200,
+				animations: {
+					dynamicAnimation: {
+						enabled: false
+					}
+				},
+				toolbar: {
+					show: false
+				},
+				zoom: {
+					enabled: false
+				}
+			},
+			dataLabels: {
+				enabled: false
+			},
+			grid: {
+				clipMarkers: false,
+				borderColor: 'rgba(0, 0, 0, 0.1)'
+			},
+			stroke: {
+				curve: 'straight',
+				width: 2
+			},
+			tooltip: {
+				enabled: false
+			},
+			legend: {
+				show: false
+			},
+			series: [{ data: [] }, { data: [] }] as any,
+			xaxis: {
+				type: 'numeric',
+				labels: {
+					show: false
+				},
+				tooltip: {
+					enabled: false
+				}
+			},
+			yaxis: {
+				show: false,
+				min: 0,
+			}
+		};
+
+		this.inChart = new ApexCharts(this.$refs.in, chartOpts);
+		this.outChart = new ApexCharts(this.$refs.out, chartOpts);
+
+		this.inChart.render();
+		this.outChart.render();
+
+		const connection = this.$root.stream.useSharedConnection('queueStats');
+		connection.on('stats', this.onStats);
+		connection.on('statsLog', this.onStatsLog);
+		connection.send('requestLog', {
+			id: Math.random().toString().substr(2, 8),
+			length: 100
+		});
+
+		this.$once('hook:beforeDestroy', () => {
+			connection.dispose();
+			this.inChart.destroy();
+			this.outChart.destroy();
+		});
+	},
+
+	methods: {
+		onStats(stats) {
+			this.stats.push(stats);
+			if (this.stats.length > 100) this.stats.shift();
+		},
+
+		onStatsLog(statsLog) {
+			for (const stats of statsLog.reverse()) {
+				this.onStats(stats);
+			}
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+.mzxlfysy
+	display flex
+
+	> div
+		display block
+		flex 1
+		padding 20px 12px 0 12px
+		box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
+		background var(--face)
+		border-radius 8px
+
+		&:first-child
+			margin-right 16px
+
+		> header
+			display flex
+			padding 0 8px
+			margin-bottom -16px
+			color var(--adminDashboardCardFg)
+			font-size 14px
+
+			> span
+				&:last-child
+					margin-left auto
+					opacity 0.7
+
+				> span
+					opacity 0.7
+
+		> div
+			margin-bottom -10px
+
+	@media (max-width 1000px)
+		display block
+		margin-bottom 26px
+
+		> div
+			&:first-child
+				margin-right 0
+				margin-bottom 26px
+
+</style>
diff --git a/src/client/app/admin/views/dashboard.vue b/src/client/app/admin/views/dashboard.vue
index b78bd9af10..f6e690f2a0 100644
--- a/src/client/app/admin/views/dashboard.vue
+++ b/src/client/app/admin/views/dashboard.vue
@@ -73,6 +73,10 @@
 		<x-charts ref="charts"/>
 	</div>
 
+	<div class="queue">
+		<x-queue/>
+	</div>
+
 	<div class="cpu-memory">
 		<x-cpu-memory :connection="connection"/>
 	</div>
@@ -87,6 +91,7 @@
 import Vue from 'vue';
 import i18n from '../../i18n';
 import XCpuMemory from "./cpu-memory.vue";
+import XQueue from "./dashboard.queue-charts.vue";
 import XCharts from "./charts.vue";
 import XApLog from "./ap-log.vue";
 import { faDatabase } from '@fortawesome/free-solid-svg-icons';
@@ -98,6 +103,7 @@ export default Vue.extend({
 
 	components: {
 		XCpuMemory,
+		XQueue,
 		XCharts,
 		XApLog,
 		MarqueeText
@@ -274,6 +280,9 @@ export default Vue.extend({
 	> .charts
 		margin-bottom 16px
 
+	> .queue
+		margin-bottom 16px
+
 	> .cpu-memory
 		margin-bottom 16px