diff --git a/atdb/taskdatabase/admin.py b/atdb/taskdatabase/admin.py
index 95916de8dbeb25a9f6a51ae6ce8644f1c040ec98..b5b030a99fc88a61d7d3183f24f084afdb206f56 100644
--- a/atdb/taskdatabase/admin.py
+++ b/atdb/taskdatabase/admin.py
@@ -1,5 +1,5 @@
 from django.contrib import admin
-from .models import Status, Task, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor
+from .models import Status, Task, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor, LatestMonitor
 
 admin.site.register(Status)
 admin.site.register(Task)
@@ -8,4 +8,5 @@ admin.site.register(LogEntry)
 admin.site.register(Configuration)
 admin.site.register(Job)
 admin.site.register(PostProcessingRule)
-admin.site.register(Monitor)
\ No newline at end of file
+admin.site.register(Monitor)
+admin.site.register(LatestMonitor)
\ No newline at end of file
diff --git a/atdb/taskdatabase/migrations/0011_auto_20220131_1103.py b/atdb/taskdatabase/migrations/0011_auto_20220131_1103.py
new file mode 100644
index 0000000000000000000000000000000000000000..8a23ea5ac23bca051d68812f6aea7d62aebeba53
--- /dev/null
+++ b/atdb/taskdatabase/migrations/0011_auto_20220131_1103.py
@@ -0,0 +1,38 @@
+# Generated by Django 3.1.4 on 2022-01-31 10:03
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('taskdatabase', '0010_auto_20220127_1458'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='LatestMonitor',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(default='unknown', max_length=50)),
+                ('type', models.CharField(blank=True, default='ldv-service', max_length=20, null=True)),
+                ('timestamp', models.DateTimeField(blank=True, default=datetime.datetime.utcnow)),
+                ('hostname', models.CharField(default='unknown', max_length=50)),
+                ('process_id', models.IntegerField(blank=True, null=True)),
+                ('description', models.CharField(blank=True, max_length=255, null=True)),
+                ('status', models.CharField(default='ok', max_length=50, null=True)),
+                ('metadata', models.JSONField(blank=True, null=True)),
+            ],
+        ),
+        migrations.AlterField(
+            model_name='monitor',
+            name='process_id',
+            field=models.IntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='monitor',
+            name='status',
+            field=models.CharField(default='ok', max_length=50, null=True),
+        ),
+    ]
diff --git a/atdb/taskdatabase/models.py b/atdb/taskdatabase/models.py
index 4aa07ef4720b749b5f81cc72d3681786e8eb0969..4ab91bf1e826348533b287cc50d603c3d207909d 100644
--- a/atdb/taskdatabase/models.py
+++ b/atdb/taskdatabase/models.py
@@ -131,8 +131,7 @@ class PostProcessingRule(models.Model):
         return str(self.aggregation_key)+' - '+str(self.trigger_status)
 
 
-
-class Monitor(models.Model):
+class LatestMonitor(models.Model):
     name = models.CharField(max_length=50, default="unknown")
     type = models.CharField(max_length=20, default="ldv-service", null=True, blank=True)
     timestamp = models.DateTimeField(default=datetime.utcnow, blank=True)
@@ -144,10 +143,10 @@ class Monitor(models.Model):
 
     # the representation of the value in the REST API
     def __str__(self):
-        return str(self.name)+' - '+str(self.timestamp) + ' - ' + self.status
+        return str(self.name) + ' - ('+ self.hostname+') - '+str(self.timestamp) + ' - ' + self.status
 
 
-class LatestMonitor(models.Model):
+class Monitor(models.Model):
     name = models.CharField(max_length=50, default="unknown")
     type = models.CharField(max_length=20, default="ldv-service", null=True, blank=True)
     timestamp = models.DateTimeField(default=datetime.utcnow, blank=True)
@@ -157,6 +156,29 @@ class LatestMonitor(models.Model):
     status = models.CharField(max_length=50, default="ok", null=True)
     metadata = models.JSONField(null=True, blank=True)
 
+    def save(self, *args, **kwargs):
+        # check if this combination of service name + hostname already exists
+        # in the LatestMonitor, and update if it is newer.
+        try:
+            latestMonitor = LatestMonitor.objects.get(name=self.name,hostname=self.hostname)
+            latestMonitor.delete()
+        except:
+            pass
+
+        # this combination of name and hostname didn't yet exist, create it.
+        latestMonitor = LatestMonitor(
+            name=self.name,
+            type=self.type,
+            timestamp=self.timestamp,
+            hostname = self.hostname,
+            process_id = self.process_id,
+            description = self.description,
+            status = self.status,
+            metadata = self.metadata
+        )
+        latestMonitor.save()
+
     # the representation of the value in the REST API
     def __str__(self):
-        return str(self.name)+' - '+str(self.timestamp) + ' - ' + self.status
\ No newline at end of file
+        return str(self.name) + ' - ('+ self.hostname+') - '+str(self.timestamp) + ' - ' + self.status
+
diff --git a/atdb/taskdatabase/serializers.py b/atdb/taskdatabase/serializers.py
index 0fa7016df238a8ff6678e81392f704df2386899b..6848e566dca13cf5031f2dd9ab6f9771d69065bc 100644
--- a/atdb/taskdatabase/serializers.py
+++ b/atdb/taskdatabase/serializers.py
@@ -1,6 +1,5 @@
 from rest_framework import serializers
-from .models import Status, Task, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor
-
+from .models import Status, Task, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor, LatestMonitor
 
 
 class WorkflowSerializer(serializers.ModelSerializer):
@@ -175,4 +174,12 @@ class MonitorSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = Monitor
-        fields = "__all__"
\ No newline at end of file
+        fields = "__all__"
+
+
+class LatestMonitorSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = LatestMonitor
+        fields = "__all__"
+        #read_only_fields = fields
\ No newline at end of file
diff --git a/atdb/taskdatabase/services/algorithms.py b/atdb/taskdatabase/services/algorithms.py
index f2784480371344954a1915765a2f37fd2aa8cd5c..4b9c9d48c1eeb1c453c657631b49c2d2939816f1 100644
--- a/atdb/taskdatabase/services/algorithms.py
+++ b/atdb/taskdatabase/services/algorithms.py
@@ -201,19 +201,39 @@ def convert_config_to_html(querylist):
     return results
 
 
-def convert_monitor_to_html(monitor_data):
+def construct_link_to_monitor_history(request, title, name, hostname):
+    query = "name=" + name + "&hostname=" + hostname
+    try:
+
+        if settings.DEV == True:
+            url = request.build_absolute_uri('/atdb/monitor/?') + query
+        else:
+            # Unclear why 'build_absolute_uri' doesn't return 'https' in production.
+            # Probably because the https is handled fully outside the container by Traefik
+            # and ATDB is not aware of that.
+
+            url = "https://" + request.get_host() + '/atdb/monitor/?' + query
+        link = '<a href="' + url + '" target="_blank">' + title + "</a>"
+    except:
+        pass
+    return link
+
+
+def convert_monitor_to_html(request, monitor_data):
     results = ""
     try:
         for record in monitor_data:
             # iterate through the dict of key/values
-            key = record.name
-            value = record.status
-            filter = record.description
+
+            # http://localhost:8000/atdb/monitor/?name=stager&hostname=localhost
+            link_to_service_history = construct_link_to_monitor_history(request, record.name, record.name, record.hostname)
+
             line = '<tr>'
             if "error" in record.status:
                 line = '<tr class="' + record.status + '" >'
 
-            line += "<td><b>" + str(record.name) + "</b></td>"
+            #line += "<td><b>" + str(record.name) + "</b></td>"
+            line += "<td><b>" + link_to_service_history + "</b></td>"
             line += "<td>" + str(record.hostname) + "</td>"
             line += '<td class="' + record.status + '" >' + str(record.status) + "</td>"
             line += "<td>" + str(record.timestamp) + "</td>"
diff --git a/atdb/taskdatabase/templates/taskdatabase/index.html b/atdb/taskdatabase/templates/taskdatabase/index.html
index 9933d22e4c21ce310f3accb479aee5d2926829c7..cb4547b6b4b48adfc2a51054b0c34e23a92666bc 100644
--- a/atdb/taskdatabase/templates/taskdatabase/index.html
+++ b/atdb/taskdatabase/templates/taskdatabase/index.html
@@ -80,7 +80,7 @@
         {% include 'taskdatabase/pagination.html' %}
        </div>
     </div>
-    <p class="footer"> Version 1.0.0 (31 jan 2021 - 10:00)
+    <p class="footer"> Version 1.0.0 (31 jan 2021 - 14:00)
 
 </div>
 
diff --git a/atdb/taskdatabase/urls.py b/atdb/taskdatabase/urls.py
index bb3272de03c04922fb39a7f962f29125896c7b2f..1ed401723967c795aaa0442415df1e7628f4c878 100644
--- a/atdb/taskdatabase/urls.py
+++ b/atdb/taskdatabase/urls.py
@@ -54,8 +54,9 @@ urlpatterns = [
     path('postprocessing/', views.PostProcessingRuleListViewAPI.as_view()),
     path('postprocessing/<int:pk>/', views.PostProcessingRuleDetailsViewAPI.as_view(), name='postprocessing-detail-view-api'),
 
-    path('monitor/', views.MonitorListViewAPI.as_view()),
+    path('monitor/', views.MonitorListViewAPI.as_view(),name='monitor-list-view-api'),
     path('monitor/<int:pk>/', views.MonitorDetailsViewAPI.as_view(),name='monitor-detail-view-api'),
+    path('latest_monitor/', views.LatestMonitorListViewAPI.as_view(),name='latest-monitor-detail-view-api'),
 
     # --- custom requests ---
     # /atdb/get_size?status__in=defined,staged
diff --git a/atdb/taskdatabase/views.py b/atdb/taskdatabase/views.py
index a1afc58587bd644268951d97438acee3f33e28c8..2edcbb504bc8e3173af3aaade390e79bb5b58e33 100644
--- a/atdb/taskdatabase/views.py
+++ b/atdb/taskdatabase/views.py
@@ -22,7 +22,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 from rest_framework.request import Request
 
 from django.conf import settings
-from .models import Task, Status, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor
+from .models import Task, Status, Workflow, LogEntry, Configuration, Job, PostProcessingRule, Monitor, LatestMonitor
 from .tables import TaskTable
 
 from django.db.models import Q
@@ -35,7 +35,8 @@ from .serializers import \
     ConfigurationSerializer, \
     JobSerializer, \
     PostProcessingRuleSerializer, \
-    MonitorSerializer
+    MonitorSerializer, LatestMonitorSerializer
+
 
 from .services import algorithms
 
@@ -138,6 +139,16 @@ class PostProcessingFilter(filters.FilterSet):
             'workflow_to_apply__id': ['exact'],
         }
 
+class MonitorFilter(filters.FilterSet):
+    class Meta:
+        model = Monitor
+
+        fields = {
+            'name': ['exact', 'icontains', 'in'],
+            'hostname': ['exact', 'icontains', 'in'],
+            'process_id': ['exact'],
+            'timestamp': ['icontains'],
+        }
 
 # ---------- Tables2 Views (experimental) -----------
 # implementation with tables2: http://localhost:8000/atdb/tables2
@@ -326,9 +337,10 @@ def WorkflowDetails(request, id):
 
 def ShowMonitoring(request):
     # get the latest value of each unique combination of service name and hostname.
-    distinct_services_per_host = Monitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', 'hostname')
+    #distinct_services_per_host = Monitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', 'hostname')
+    distinct_services_per_host = LatestMonitor.objects.all().order_by('name', 'hostname', '-timestamp').distinct('name', 'hostname')
 
-    monitor_results = algorithms.convert_monitor_to_html(distinct_services_per_host)
+    monitor_results = algorithms.convert_monitor_to_html(request, distinct_services_per_host)
     return render(request, "taskdatabase/monitoring.html", {'monitor_results': monitor_results})
 
 
@@ -545,14 +557,24 @@ class PostProcessingRuleDetailsViewAPI(generics.RetrieveUpdateDestroyAPIView):
     serializer_class = PostProcessingRuleSerializer
 
 
-# example: /atdb/job/
+# example: /atdb/monitor/
 class MonitorListViewAPI(generics.ListCreateAPIView):
     model = Monitor
-    queryset = Monitor.objects.all()
+    queryset = Monitor.objects.all().order_by('-timestamp')
     serializer_class = MonitorSerializer
 
     filter_backends = (filters.DjangoFilterBackend,)
-    # filter_class = PostProcessingFilter
+    filter_class = MonitorFilter
+
+
+# example: /atdb/latest-monitor/
+class LatestMonitorListViewAPI(generics.ListCreateAPIView):
+    model = LatestMonitor
+    queryset = LatestMonitor.objects.all()
+    serializer_class = LatestMonitorSerializer
+
+    filter_backends = (filters.DjangoFilterBackend,)
+    filter_class = MonitorFilter
 
 
 # example: /atdb/job/5/