diff --git a/docs/api-reference/crds.md b/docs/api-reference/crds.md
index a91e991609f5fe10e90793f34f2ad04c6c5576d0..0d7e46e3a72aea642fdc629f1abb664a4f8b93f3 100644
--- a/docs/api-reference/crds.md
+++ b/docs/api-reference/crds.md
@@ -2069,10 +2069,19 @@ Specifies the scaling resource that is benchmarked.
         </tr>
     </thead>
     <tbody><tr>
+        <td><b>completionTime</b></td>
+        <td>string</td>
+        <td>
+          Time when this execution was stopped<br/>
+          <br/>
+            <i>Format</i>: date-time<br/>
+        </td>
+        <td>false</td>
+      </tr><tr>
         <td><b>executionDuration</b></td>
         <td>string</td>
         <td>
-          Duration of the execution in seconds<br/>
+          Duration of the execution<br/>
         </td>
         <td>false</td>
       </tr><tr>
@@ -2082,5 +2091,14 @@ Specifies the scaling resource that is benchmarked.
           <br/>
         </td>
         <td>false</td>
+      </tr><tr>
+        <td><b>startTime</b></td>
+        <td>string</td>
+        <td>
+          Time this execution started<br/>
+          <br/>
+            <i>Format</i>: date-time<br/>
+        </td>
+        <td>false</td>
       </tr></tbody>
 </table>
\ No newline at end of file
diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml
index cd9c9f1e07c38a8727bcd23939319c0955e07645..55bf6ed69e44287905bce85b63f66bb43ea65669 100644
--- a/theodolite/crd/crd-benchmark.yaml
+++ b/theodolite/crd/crd-benchmark.yaml
@@ -467,7 +467,7 @@ spec:
     - name: Age
       type: date
       jsonPath: .metadata.creationTimestamp
-    - name: STATUS
+    - name: Status
       type: string
       description: The status of a Benchmark indicates whether all resources are available to start the benchmark or not.
       jsonPath: .status.resourceSetsState
diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml
index d9cd41903bb2fdc18bd6640bdbe2eb764b2106ab..92a8ca18d87009143620097caf2abfe8da202c82 100644
--- a/theodolite/crd/crd-execution.yaml
+++ b/theodolite/crd/crd-execution.yaml
@@ -133,10 +133,18 @@ spec:
                 description: ""
                 type: string
               executionDuration:
-                description: "Duration of the execution in seconds"
+                description: "Duration of the execution"
                 type: string
+              startTime:
+                description: "Time this execution started"
+                type: string
+                format: date-time
+              completionTime:
+                description: "Time when this execution was stopped"
+                type: string
+                format: date-time
     additionalPrinterColumns:
-    - name: STATUS
+    - name: Status
       type: string
       description: State of the execution
       jsonPath: .status.executionState
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
index 8cd469394ac8f2b67d73a0b3d2565cd0f37d7318..93536282e2eefe6e476c3fde3fd86860fa24dcc3 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
@@ -2,8 +2,6 @@ package theodolite.execution.operator
 
 import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.KubernetesResourceList
-import io.fabric8.kubernetes.api.model.Namespaced
-import io.fabric8.kubernetes.client.CustomResource
 import io.fabric8.kubernetes.client.KubernetesClientException
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
 import io.fabric8.kubernetes.client.dsl.MixedOperation
@@ -14,19 +12,19 @@ private val logger = KotlinLogging.logger {}
 
 private const val MAX_RETRIES: Int = 5
 
-abstract class AbstractStateHandler<T : HasMetadata>(
+abstract class AbstractStateHandler<S : HasMetadata>(
     private val client: NamespacedKubernetesClient,
-    private val crd: Class<T>
+    private val crd: Class<S>
 ) {
 
-    private val crdClient: MixedOperation<T, KubernetesResourceList<T>, Resource<T>> = this.client.resources(this.crd)
+    private val crdClient: MixedOperation<S, KubernetesResourceList<S>, Resource<S>> = this.client.resources(this.crd)
 
     @Synchronized
-    fun setState(resourceName: String, f: (T) -> T?) {
+    fun setState(resourceName: String, setter: (S) -> S?) {
         try {
             val resource = this.crdClient.withName(resourceName).get()
             if (resource != null) {
-                val resourcePatched = f(resource)
+                val resourcePatched = setter(resource)
                 this.crdClient.patchStatus(resourcePatched)
             }
         } catch (e: KubernetesClientException) {
@@ -35,7 +33,7 @@ abstract class AbstractStateHandler<T : HasMetadata>(
     }
 
     @Synchronized
-    fun getState(resourceName: String, f: (T) -> String?): String? {
+    fun getState(resourceName: String, f: (S) -> String?): String? {
         return this.crdClient
             .list().items
             .filter { it.metadata.name == resourceName }
@@ -47,7 +45,7 @@ abstract class AbstractStateHandler<T : HasMetadata>(
     fun blockUntilStateIsSet(
         resourceName: String,
         desiredStatusString: String,
-        f: (T) -> String?,
+        f: (S) -> String?,
         maxRetries: Int = MAX_RETRIES
     ): Boolean {
         for (i in 0.rangeTo(maxRetries)) {
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt
index 959b04a8e5c94806aea1753af56b2518436aed12..40f5b7ddbbfc9da4514b8a88946d97149b94b390 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt
@@ -10,7 +10,7 @@ import theodolite.benchmark.ActionSelector
 import theodolite.benchmark.KubernetesBenchmark
 import theodolite.benchmark.ResourceSets
 import theodolite.model.crd.BenchmarkCRD
-import theodolite.model.crd.BenchmarkStates
+import theodolite.model.crd.BenchmarkState
 import theodolite.model.crd.KubernetesBenchmarkList
 
 class BenchmarkStateChecker(
@@ -42,7 +42,7 @@ class BenchmarkStateChecker(
             .forEach { setState(it.first, it.second) }
     }
 
-    private fun setState(resource: BenchmarkCRD, state: BenchmarkStates) {
+    private fun setState(resource: BenchmarkCRD, state: BenchmarkState) {
         benchmarkStateHandler.setResourceSetState(resource.spec.name, state)
     }
 
@@ -52,13 +52,13 @@ class BenchmarkStateChecker(
      * @param benchmark The benchmark to check
      * @return [BenchmarkStates.READY] iff all resource could be loaded and all actions could be executed, [BenchmarkStates.PENDING] else
      */
-    private fun checkState(benchmark: KubernetesBenchmark): BenchmarkStates {
-        return if (checkActionCommands(benchmark) == BenchmarkStates.READY
-            && checkResources(benchmark) == BenchmarkStates.READY
+    private fun checkState(benchmark: KubernetesBenchmark): BenchmarkState {
+        return if (checkActionCommands(benchmark) == BenchmarkState.READY
+            && checkResources(benchmark) == BenchmarkState.READY
         ) {
-            BenchmarkStates.READY
+            BenchmarkState.READY
         } else {
-            BenchmarkStates.PENDING
+            BenchmarkState.PENDING
         }
     }
 
@@ -68,15 +68,15 @@ class BenchmarkStateChecker(
      * @param benchmark The benchmark to check
      * @return The state of this benchmark. [BenchmarkStates.READY] if all actions could be executed, else [BenchmarkStates.PENDING]
      */
-    private fun checkActionCommands(benchmark: KubernetesBenchmark): BenchmarkStates {
+    private fun checkActionCommands(benchmark: KubernetesBenchmark): BenchmarkState {
         return if (checkIfActionPossible(benchmark.infrastructure.resources, benchmark.sut.beforeActions)
             && checkIfActionPossible(benchmark.infrastructure.resources, benchmark.sut.afterActions)
             && checkIfActionPossible(benchmark.infrastructure.resources, benchmark.loadGenerator.beforeActions)
             && checkIfActionPossible(benchmark.infrastructure.resources, benchmark.loadGenerator.beforeActions)
         ) {
-            BenchmarkStates.READY
+            BenchmarkState.READY
         } else {
-            BenchmarkStates.PENDING
+            BenchmarkState.PENDING
         }
     }
 
@@ -171,21 +171,21 @@ class BenchmarkStateChecker(
      * Checks if it is possible to load all specified Kubernetes manifests.
      *
      * @param benchmark The benchmark to check
-     * @return The state of this benchmark. [BenchmarkStates.READY] if all resources could be loaded, else [BenchmarkStates.PENDING]
+     * @return The state of this benchmark. [BenchmarkState.READY] if all resources could be loaded, else [BenchmarkState.PENDING]
      */
-    fun checkResources(benchmark: KubernetesBenchmark): BenchmarkStates {
+    fun checkResources(benchmark: KubernetesBenchmark): BenchmarkState {
         return try {
             val appResources =
                 benchmark.loadKubernetesResources(resourceSet = benchmark.sut.resources)
             val loadGenResources =
                 benchmark.loadKubernetesResources(resourceSet = benchmark.loadGenerator.resources)
             if (appResources.isNotEmpty() && loadGenResources.isNotEmpty()) {
-                BenchmarkStates.READY
+                BenchmarkState.READY
             } else {
-                BenchmarkStates.PENDING
+                BenchmarkState.PENDING
             }
         } catch (e: Exception) {
-            BenchmarkStates.PENDING
+            BenchmarkState.PENDING
         }
     }
 }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
index 80cee0a3a30c0734ff2e12ef0d0291015d157f9c..3b46859737d86a34b58a5514c0ae31ae215b9c7d 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt
@@ -9,19 +9,19 @@ class BenchmarkStateHandler(val client: NamespacedKubernetesClient) :
         crd = BenchmarkCRD::class.java
     ) {
 
-    private fun getBenchmarkResourceState() = { cr: BenchmarkCRD -> cr.status.resourceSetsState }
+    private fun getBenchmarkResourceState() = { cr: BenchmarkCRD -> cr.status.resourceSetsState.value }
 
-    fun setResourceSetState(resourceName: String, status: BenchmarkStates): Boolean {
-        setState(resourceName) { cr -> cr.status.resourceSetsState = status.value; cr }
+    fun setResourceSetState(resourceName: String, status: BenchmarkState): Boolean {
+        setState(resourceName) { cr -> cr.status.resourceSetsState = status; cr }
         return blockUntilStateIsSet(resourceName, status.value, getBenchmarkResourceState())
     }
 
-    fun getResourceSetState(resourceName: String): ExecutionStates {
+    fun getResourceSetState(resourceName: String): ExecutionState {
         val status = this.getState(resourceName, getBenchmarkResourceState())
         return if (status.isNullOrBlank()) {
-            ExecutionStates.NO_STATE
+            ExecutionState.NO_STATE
         } else {
-            ExecutionStates.values().first { it.value == status }
+            ExecutionState.values().first { it.value == status }
         }
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
index 6e0f9fa39a3d925c0e7d6f77b01f82ef1874deb1..885315df6eda0d91a27567720056738b997a8ec1 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
@@ -38,7 +38,7 @@ class ClusterSetup(
             .list()
             .items
             .asSequence()
-            .filter { it.status.executionState == ExecutionStates.RUNNING.value }
+            .filter { it.status.executionState == ExecutionState.RUNNING }
             .forEach { execution ->
                 val benchmark = benchmarkCRDClient
                     .inNamespace(client.namespace)
@@ -51,7 +51,7 @@ class ClusterSetup(
                     benchmark.spec.name = benchmark.metadata.name
                     Shutdown(execution.spec, benchmark.spec).run()
                 } else {
-                    throw IllegalStateException("Execution with state ${ExecutionStates.RUNNING.value} was found, but no corresponding benchmark. " +
+                    throw IllegalStateException("Execution with state ${ExecutionState.RUNNING.value} was found, but no corresponding benchmark. " +
                             "Could not initialize cluster.")
                 }
             }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
index 86276af35dd13457cb6c971144153612705dc420..25c627a350e3939530c4b453ec6db846b546cc08 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
@@ -34,9 +34,9 @@ class ExecutionEventHandler(
         logger.info { "Add execution ${execution.metadata.name}." }
         execution.spec.name = execution.metadata.name
         when (this.stateHandler.getExecutionState(execution.metadata.name)) {
-            ExecutionStates.NO_STATE -> this.stateHandler.setExecutionState(execution.spec.name, ExecutionStates.PENDING)
-            ExecutionStates.RUNNING -> {
-                this.stateHandler.setExecutionState(execution.spec.name, ExecutionStates.RESTART)
+            ExecutionState.NO_STATE -> this.stateHandler.setExecutionState(execution.spec.name, ExecutionState.PENDING)
+            ExecutionState.RUNNING -> {
+                this.stateHandler.setExecutionState(execution.spec.name, ExecutionState.RESTART)
                 if (this.controller.isExecutionRunning(execution.spec.name)) {
                     this.controller.stop(restart = true)
                 }
@@ -59,15 +59,15 @@ class ExecutionEventHandler(
         if (gson.toJson(oldExecution.spec) != gson.toJson(newExecution.spec)) {
             logger.info { "Receive update event for execution ${oldExecution.metadata.name}." }
             when (this.stateHandler.getExecutionState(newExecution.metadata.name)) {
-                ExecutionStates.RUNNING -> {
-                    this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionStates.RESTART)
+                ExecutionState.RUNNING -> {
+                    this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionState.RESTART)
                     if (this.controller.isExecutionRunning(newExecution.spec.name)) {
                         this.controller.stop(restart = true)
                     }
                 }
-                ExecutionStates.RESTART -> {
+                ExecutionState.RESTART -> {
                 } // should this set to pending?
-                else -> this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionStates.PENDING)
+                else -> this.stateHandler.setExecutionState(newExecution.spec.name, ExecutionState.PENDING)
             }
         }
     }
@@ -80,7 +80,7 @@ class ExecutionEventHandler(
     @Synchronized
     override fun onDelete(execution: ExecutionCRD, deletedFinalStateUnknown: Boolean) {
         logger.info { "Delete execution ${execution.metadata.name}." }
-        if (execution.status.executionState == ExecutionStates.RUNNING.value
+        if (execution.status.executionState == ExecutionState.RUNNING
             && this.controller.isExecutionRunning(execution.metadata.name)
         ) {
             this.controller.stop()
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
index a412805621fc7868d1efc215cdf4ff81b52d914e..340044e5be954d4d7673120e5bf2cba5aed02d92 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
@@ -1,12 +1,10 @@
 package theodolite.execution.operator
 
+import io.fabric8.kubernetes.api.model.MicroTime
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import theodolite.model.crd.BenchmarkExecutionList
 import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionStatus
-import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionState
 import java.lang.Thread.sleep
-import java.time.Duration
 import java.time.Instant
 import java.util.concurrent.atomic.AtomicBoolean
 
@@ -18,58 +16,39 @@ class ExecutionStateHandler(val client: NamespacedKubernetesClient) :
 
     private var runExecutionDurationTimer: AtomicBoolean = AtomicBoolean(false)
 
-    private fun getExecutionLambda() = { cr: ExecutionCRD -> cr.status.executionState }
+    private fun getExecutionLambda() = { cr: ExecutionCRD -> cr.status.executionState.value }
 
-    private fun getDurationLambda() = { cr: ExecutionCRD -> cr.status.executionDuration }
-
-    fun setExecutionState(resourceName: String, status: ExecutionStates): Boolean {
-        super.setState(resourceName) { cr -> cr.status.executionState = status.value; cr }
+    fun setExecutionState(resourceName: String, status: ExecutionState): Boolean {
+        super.setState(resourceName) { cr -> cr.status.executionState = status; cr }
         return blockUntilStateIsSet(resourceName, status.value, getExecutionLambda())
     }
 
-    fun getExecutionState(resourceName: String): ExecutionStates {
-        val status = this.getState(resourceName, getExecutionLambda())
-        return if (status.isNullOrBlank()) {
-            ExecutionStates.NO_STATE
-        } else {
-            ExecutionStates.values().first { it.value == status }
-        }
-    }
-
-    fun setDurationState(resourceName: String, duration: Duration): Boolean {
-        setState(resourceName) { cr -> cr.status.executionDuration = durationToK8sString(duration); cr }
-        return blockUntilStateIsSet(resourceName, durationToK8sString(duration), getDurationLambda())
+    fun getExecutionState(resourceName: String): ExecutionState {
+        val statusString = this.getState(resourceName, getExecutionLambda())
+        return ExecutionState.values().first { it.value == statusString }
     }
 
-    fun getDurationState(resourceName: String): String {
-        val status = getState(resourceName, getDurationLambda())
-        return if (status.isNullOrBlank()) "-" else status
-    }
-
-    private fun durationToK8sString(duration: Duration): String {
-        val sec = duration.seconds
-        return when {
-            sec <= 120 -> "${sec}s" // max 120s
-            sec < 60 * 99 -> "${duration.toMinutes()}m" // max 99m
-            sec < 60 * 60 * 99 -> "${duration.toHours()}h"   // max 99h
-            else -> "${duration.toDays()}d + ${duration.minusDays(duration.toDays()).toHours()}h"
-        }
+    private fun updateDurationState(resourceName: String) {
+        super.setState(resourceName) { cr -> cr }
     }
 
     fun startDurationStateTimer(resourceName: String) {
         this.runExecutionDurationTimer.set(true)
-        val startTime = Instant.now().toEpochMilli()
+
+        super.setState(resourceName) { cr -> cr.status.completionTime = null; cr }
+        super.setState(resourceName) { cr -> cr.status.startTime = MicroTime(Instant.now().toString()); cr }
+
         Thread {
             while (this.runExecutionDurationTimer.get()) {
-                val duration = Duration.ofMillis(Instant.now().minusMillis(startTime).toEpochMilli())
-                setDurationState(resourceName, duration)
+                updateDurationState(resourceName)
                 sleep(100 * 1)
             }
         }.start()
     }
 
     @Synchronized
-    fun stopDurationStateTimer() {
+    fun stopDurationStateTimer(resourceName: String) {
+        super.setState(resourceName) { cr -> cr.status.completionTime = MicroTime(Instant.now().toString()); cr }
         this.runExecutionDurationTimer.set(false)
         sleep(100 * 2)
     }
diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
index a23c1506b4d46aa9f87c3a4cd05bb0a8c7dcd570..2b6f83c76ce6e31f85cdfec1962f9523c3d297b8 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
@@ -85,20 +85,20 @@ class TheodoliteController(
             labelName = CREATED_BY_LABEL_NAME
         )
 
-        executionStateHandler.setExecutionState(execution.name, ExecutionStates.RUNNING)
+        executionStateHandler.setExecutionState(execution.name, ExecutionState.RUNNING)
         executionStateHandler.startDurationStateTimer(execution.name)
 
             executor = TheodoliteExecutor(execution, benchmark)
             executor.run()
             when (executionStateHandler.getExecutionState(execution.name)) {
-                ExecutionStates.RESTART -> runExecution(execution, benchmark)
-                ExecutionStates.RUNNING -> {
-                    executionStateHandler.setExecutionState(execution.name, ExecutionStates.FINISHED)
+                ExecutionState.RESTART -> runExecution(execution, benchmark)
+                ExecutionState.RUNNING -> {
+                    executionStateHandler.setExecutionState(execution.name, ExecutionState.FINISHED)
                     logger.info { "Execution of ${execution.name} is finally stopped." }
                     }
                 else -> {
-                    executionStateHandler.setExecutionState(execution.name, ExecutionStates.FAILURE)
-                    logger.warn { "Unexpected execution state, set state to ${ExecutionStates.FAILURE.value}" }
+                    executionStateHandler.setExecutionState(execution.name, ExecutionState.FAILURE)
+                    logger.warn { "Unexpected execution state, set state to ${ExecutionState.FAILURE.value}" }
                 }
             }
         } catch (e: Exception) {
@@ -108,16 +108,16 @@ class TheodoliteController(
                 reason = "Execution failed",
                 message = "An error occurs while executing:  ${e.message}")
             logger.error(e) { "Failure while executing execution ${execution.name} with benchmark ${benchmark.name}." }
-            executionStateHandler.setExecutionState(execution.name, ExecutionStates.FAILURE)
+            executionStateHandler.setExecutionState(execution.name, ExecutionState.FAILURE)
         }
-        executionStateHandler.stopDurationStateTimer()
+        executionStateHandler.stopDurationStateTimer(execution.name)
     }
 
     @Synchronized
     fun stop(restart: Boolean = false) {
         if (!::executor.isInitialized) return
         if (restart) {
-            executionStateHandler.setExecutionState(this.executor.getExecution().name, ExecutionStates.RESTART)
+            executionStateHandler.setExecutionState(this.executor.getExecution().name, ExecutionState.RESTART)
         }
         this.executor.executor.run.set(false)
     }
@@ -140,16 +140,16 @@ class TheodoliteController(
      * is selected for the next execution depends on three points:
      *
      * 1. Only executions are considered for which a matching benchmark is available on the cluster
-     * 2. The Status of the execution must be [ExecutionStates.PENDING] or [ExecutionStates.RESTART]
-     * 3. Of the remaining [BenchmarkCRD], those with status [ExecutionStates.RESTART] are preferred,
+     * 2. The Status of the execution must be [ExecutionState.PENDING] or [ExecutionState.RESTART]
+     * 3. Of the remaining [BenchmarkCRD], those with status [ExecutionState.RESTART] are preferred,
      * then, if there is more than one, the oldest execution is chosen.
      *
      * @return the next execution or null
      */
     private fun getNextExecution(): BenchmarkExecution? {
-        val comparator = ExecutionStateComparator(ExecutionStates.RESTART)
+        val comparator = ExecutionStateComparator(ExecutionState.RESTART)
         val availableBenchmarkNames = getBenchmarks()
-            .filter { it.status.resourceSetsState == BenchmarkStates.READY.value }
+            .filter { it.status.resourceSetsState == BenchmarkState.READY }
             .map { it.spec }
             .map { it.name }
 
@@ -159,8 +159,7 @@ class TheodoliteController(
             .asSequence()
             .map { it.spec.name = it.metadata.name; it }
             .filter {
-                it.status.executionState == ExecutionStates.PENDING.value ||
-                        it.status.executionState == ExecutionStates.RESTART.value
+                it.status.executionState == ExecutionState.PENDING || it.status.executionState == ExecutionState.RESTART
             }
             .filter { availableBenchmarkNames.contains(it.spec.benchmark) }
             .sortedWith(comparator.thenBy { it.metadata.creationTimestamp })
@@ -168,8 +167,6 @@ class TheodoliteController(
             .firstOrNull()
     }
 
-
-
     fun isExecutionRunning(executionName: String): Boolean {
         if (!::executor.isInitialized) return false
         return this.executor.getExecution().name == executionName
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
index 2e9ffafb83734b3daceb3e9e523e900b887d785a..0ec6decbdea5e192721a4f9b6d0d85ea65665a5a 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
@@ -1,20 +1,18 @@
 package theodolite.model.crd
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import io.fabric8.kubernetes.api.model.HasMetadata
 import io.fabric8.kubernetes.api.model.Namespaced
 import io.fabric8.kubernetes.client.CustomResource
 import io.fabric8.kubernetes.model.annotation.Group
 import io.fabric8.kubernetes.model.annotation.Kind
 import io.fabric8.kubernetes.model.annotation.Version
-import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 
 @JsonDeserialize
 @Version("v1")
 @Group("theodolite.com")
 @Kind("benchmark")
-class BenchmarkCRD : CustomResource<KubernetesBenchmark, BenchmarkStatus>(), Namespaced, HasMetadata {
+class BenchmarkCRD : CustomResource<KubernetesBenchmark, BenchmarkStatus>(), Namespaced {
 
     override fun initSpec(): KubernetesBenchmark {
         return KubernetesBenchmark()
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dc2c6f9ba971367c0bb142a54745629eb29c07d5
--- /dev/null
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt
@@ -0,0 +1,8 @@
+package theodolite.model.crd
+
+import com.fasterxml.jackson.annotation.JsonValue
+
+enum class BenchmarkState(@JsonValue val value: String) {
+    PENDING("Pending"),
+    READY("Ready")
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStates.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStates.kt
deleted file mode 100644
index f52f2c168765ebb8bcc4f390795aa470b968021b..0000000000000000000000000000000000000000
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStates.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package theodolite.model.crd
-
-enum class BenchmarkStates(val value: String) {
-    PENDING("Pending"),
-    READY("Ready")
-}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
index f51cb7a76d015d6ecd900279e68d41baa26e876a..d4a17dbefb6cf3a53d545c32cb18e1d9acd7067f 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt
@@ -6,6 +6,6 @@ import io.fabric8.kubernetes.api.model.Namespaced
 
 @JsonDeserialize
 class BenchmarkStatus: KubernetesResource, Namespaced {
-    var resourceSetsState = "-"
+    var resourceSetsState: BenchmarkState = BenchmarkState.PENDING
 
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt
similarity index 65%
rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
rename to theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt
index 368fc39a3cba1bc702f1f0831c96637a61548358..9ce38d9f56a968ccc408966e56609ee4f70570a4 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStates.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt
@@ -1,6 +1,8 @@
 package theodolite.model.crd
 
-enum class ExecutionStates(val value: String) {
+import com.fasterxml.jackson.annotation.JsonValue
+
+enum class ExecutionState(@JsonValue val value: String) {
     RUNNING("Running"),
     PENDING("Pending"),
     FAILURE("Failure"),
diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
index 252738959762aa5d0732babc5589c698d7bd4e9f..1f843ccf9152676e778bc4ed359776e37205e998 100644
--- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
+++ b/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
@@ -1,11 +1,58 @@
 package theodolite.model.crd
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties
+import com.fasterxml.jackson.core.JsonGenerator
+import com.fasterxml.jackson.databind.JsonSerializer
+import com.fasterxml.jackson.databind.SerializerProvider
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import com.fasterxml.jackson.databind.annotation.JsonSerialize
+import io.fabric8.kubernetes.api.model.Duration
 import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.MicroTime
 import io.fabric8.kubernetes.api.model.Namespaced
+import java.time.Clock
+import java.time.Instant
+import java.time.Duration as JavaDuration
+
 
 @JsonDeserialize
-class ExecutionStatus : KubernetesResource, Namespaced {
-    var executionState: String = ""
-    var executionDuration: String = "-"
+@JsonIgnoreProperties(ignoreUnknown = true)
+class ExecutionStatus(
+    private val clock: Clock = Clock.systemUTC()
+) : KubernetesResource, Namespaced {
+
+    var executionState: ExecutionState = ExecutionState.NO_STATE
+
+    var startTime: MicroTime? = null
+
+    var completionTime: MicroTime? = null
+
+    @get:JsonSerialize(using = DurationSerializer::class)
+    val executionDuration: Duration?
+        get() {
+            val startTime = this.startTime?.toInstant()
+            val completionTime = this.completionTime?.toInstant() ?: clock.instant()!!
+            return startTime?.let {Duration(JavaDuration.between(it, completionTime)) }
+        }
+
+    private fun MicroTime.toInstant(): Instant {
+        return Instant.parse(this.time)
+    }
+
+    class DurationSerializer : JsonSerializer<Duration?>() {
+
+        override fun serialize(duration: Duration?, generator: JsonGenerator, serProvider: SerializerProvider) {
+            generator.writeObject(duration?.duration?.toK8sString())
+        }
+
+        private fun JavaDuration.toK8sString(): String {
+            return when {
+                this <= JavaDuration.ofSeconds(2)  -> "${this.toSeconds()}s"
+                this < JavaDuration.ofMinutes(99) -> "${this.toMinutes()}m"
+                this < JavaDuration.ofHours(99) -> "${this.toHours()}h"
+                else -> "${this.toDays()}d + ${this.minusDays(this.toDays()).toHours()}h"
+            }
+        }
+
+    }
 }
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt b/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
index c8f0160c72ae85547e2988ea368c8d1a7a1b5651..81bf350b58901bc10535f143d5ccdb295b5fe85f 100644
--- a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt
@@ -1,17 +1,17 @@
 package theodolite.util
 
 import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionState
 
-class ExecutionStateComparator(private val preferredState: ExecutionStates): Comparator<ExecutionCRD> {
+class ExecutionStateComparator(private val preferredState: ExecutionState): Comparator<ExecutionCRD> {
 
     /**
      * Simple comparator which can be used to order a list of [ExecutionCRD]s such that executions with
-     * status [ExecutionStates.RESTART] are before all other executions.
+     * status [ExecutionState.RESTART] are before all other executions.
      */
     override fun compare(p0: ExecutionCRD, p1: ExecutionCRD): Int {
        return when {
-            (p0.status.executionState == preferredState.value) -> -1
+            (p0.status.executionState == preferredState) -> -1
             else -> 1
         }
     }
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt
index f3af42548d3bfc0d12e9f664d11cce1ae424e748..528cfac8066c28bf6382fb97cddf280b3c1de622 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt
@@ -14,7 +14,7 @@ import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.Assertions.*
 import theodolite.benchmark.*
-import theodolite.model.crd.BenchmarkStates
+import theodolite.model.crd.BenchmarkState
 
 internal class BenchmarkStateCheckerTest {
     private val server = KubernetesServer(false, false)
@@ -172,6 +172,6 @@ internal class BenchmarkStateCheckerTest {
         benchmark.getCR().spec.loadGenerator = resourceSet
         benchmark.getCR().spec.sut = resourceSet
 
-        assertEquals(BenchmarkStates.READY,checkerCrud.checkResources(benchmark.getCR().spec))
+        assertEquals(BenchmarkState.READY,checkerCrud.checkResources(benchmark.getCR().spec))
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
index 6ea69689847afeb8f9fc36de2944c6fdcf4702ad..7d40f7e45d6aa2c93206a1bad22754fe93b0c100 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
@@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 import theodolite.model.crd.BenchmarkCRD
-import theodolite.model.crd.BenchmarkStates
+import theodolite.model.crd.BenchmarkState
 import theodolite.model.crd.ExecutionCRD
 
 @QuarkusTest
@@ -41,7 +41,7 @@ class ControllerTest {
 
         // benchmark
         val benchmark1 = BenchmarkCRDummy(name = "Test-Benchmark")
-        benchmark1.getCR().status.resourceSetsState = BenchmarkStates.READY.value
+        benchmark1.getCR().status.resourceSetsState = BenchmarkState.READY
         val benchmark2 = BenchmarkCRDummy(name = "Test-Benchmark-123")
         benchmarkResourceList.items = listOf(benchmark1.getCR(), benchmark2.getCR())
 
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
index e8010f345140f41dc2edfbe387316f6d21511915..9274e283b48a6fd9b30d5ce0aff3cb8b995e0ce5 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
@@ -3,7 +3,7 @@ package theodolite.execution.operator
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.model.crd.ExecutionCRD
 import theodolite.model.crd.ExecutionStatus
-import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionState
 
 class ExecutionCRDummy(name: String, benchmark: String) {
 
@@ -52,6 +52,6 @@ class ExecutionCRDummy(name: String, benchmark: String) {
         execution.configOverrides = mutableListOf()
         execution.name = executionCR.metadata.name
 
-        executionState.executionState = ExecutionStates.PENDING.value
+        executionState.executionState = ExecutionState.PENDING
     }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
index ec14d7d8fefb384efc53d79f3b9772c4ccc1e270..c08e0565375de84a228a28b6d68a0b713af97d0f 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt
@@ -17,10 +17,8 @@ import org.junit.jupiter.params.provider.Arguments
 import org.junit.jupiter.params.provider.MethodSource
 import org.mockito.kotlin.*
 import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionStates
-import theodolite.model.crd.ExecutionStatus
+import theodolite.model.crd.ExecutionState
 import java.io.FileInputStream
-import java.lang.Thread.sleep
 import java.util.stream.Stream
 
 // TODO move somewhere else
@@ -99,7 +97,7 @@ class ExecutionEventHandlerTest {
         val executionResponse = this.executionClient.withName(executionName).get()
         this.eventHandler.onAdd(executionResponse)
 
-        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.PENDING, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
@@ -109,24 +107,24 @@ class ExecutionEventHandlerTest {
         val executionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
         val execution = executionResource.create()
         val executionName = execution.metadata.name
-        stateHandler.setExecutionState(executionName, ExecutionStates.RUNNING)
+        stateHandler.setExecutionState(executionName, ExecutionState.RUNNING)
 
         // Update status of execution
-        execution.status.executionState = ExecutionStates.RUNNING.value
+        execution.status.executionState = ExecutionState.RUNNING
         executionResource.patchStatus(execution)
 
 
         // Get execution from server
         val executionResponse = this.executionClient.withName(executionName).get()
         // Assert that status at server matches set status
-        assertEquals(ExecutionStates.RUNNING.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.RUNNING, this.executionClient.withName(executionName).get().status.executionState)
 
         whenever(this.controller.isExecutionRunning(executionName)).thenReturn(true)
 
         this.eventHandler.onAdd(executionResponse)
 
         verify(this.controller).stop(true)
-        assertEquals(ExecutionStates.RESTART.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.RESTART, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
@@ -140,7 +138,7 @@ class ExecutionEventHandlerTest {
         // Get execution from server
         val firstExecutionResponse = this.executionClient.withName(executionName).get()
         // Assert that execution at server has no status
-        assertEquals("", firstExecutionResponse.status.executionState)
+        assertEquals(ExecutionState.NO_STATE, firstExecutionResponse.status.executionState)
 
         // Create new version of execution and update at server
         getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
@@ -150,26 +148,26 @@ class ExecutionEventHandlerTest {
         this.eventHandler.onUpdate(firstExecutionResponse, secondExecutionResponse)
 
         // Get execution from server and assert that new status matches expected one
-        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.PENDING, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @ParameterizedTest
     @MethodSource("provideOnUpdateTestArguments")
     @DisplayName("Test onUpdate method for execution with different status")
-    fun testOnUpdateWithStatus(beforeState: ExecutionStates, expectedState: ExecutionStates) {
+    fun testOnUpdateWithStatus(beforeState: ExecutionState, expectedState: ExecutionState) {
         // Create first version of execution resource
         val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
         val firstExecution = firstExecutionResource.create()
         val executionName = firstExecution.metadata.name
 
         // Update status of execution
-        firstExecution.status.executionState = beforeState.value
+        firstExecution.status.executionState = beforeState
         firstExecutionResource.patchStatus(firstExecution)
 
         // Get execution from server
         val firstExecutionResponse = this.executionClient.withName(executionName).get()
         // Assert that status at server matches set status
-        assertEquals(beforeState.value, firstExecutionResponse.status.executionState)
+        assertEquals(beforeState, firstExecutionResponse.status.executionState)
 
         // Create new version of execution and update at server
         getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
@@ -179,7 +177,7 @@ class ExecutionEventHandlerTest {
         this.eventHandler.onUpdate(firstExecutionResponse, secondExecutionResponse)
 
         // Get execution from server and assert that new status matches expected one
-        assertEquals(expectedState.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(expectedState, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
@@ -190,7 +188,7 @@ class ExecutionEventHandlerTest {
         val executionName = firstExecution.metadata.name
 
         // Update status of execution to be running
-        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecution.status.executionState = ExecutionState.RUNNING
         firstExecutionResource.patchStatus(firstExecution)
 
         // Get execution from server
@@ -222,7 +220,7 @@ class ExecutionEventHandlerTest {
         val executionName = firstExecution.metadata.name
 
         // Update status of execution to be running
-        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecution.status.executionState = ExecutionState.RUNNING
         firstExecutionResource.patchStatus(firstExecution)
 
         // Get execution from server
@@ -240,7 +238,7 @@ class ExecutionEventHandlerTest {
 
         // We consider execution to be running
         whenever(this.controller.isExecutionRunning(executionName)).thenReturn(false)
-        
+
         this.eventHandler.onDelete(firstExecutionResponse, true)
 
         verify(this.controller, never()).stop(false)
@@ -255,11 +253,11 @@ class ExecutionEventHandlerTest {
         fun provideOnUpdateTestArguments(): Stream<Arguments> =
             Stream.of(
                 // before state -> expected state
-                Arguments.of(ExecutionStates.PENDING, ExecutionStates.PENDING),
-                Arguments.of(ExecutionStates.FINISHED, ExecutionStates.PENDING),
-                Arguments.of(ExecutionStates.FAILURE, ExecutionStates.PENDING),
-                Arguments.of(ExecutionStates.RUNNING, ExecutionStates.RESTART),
-                Arguments.of(ExecutionStates.RESTART, ExecutionStates.RESTART)
+                Arguments.of(ExecutionState.PENDING, ExecutionState.PENDING),
+                Arguments.of(ExecutionState.FINISHED, ExecutionState.PENDING),
+                Arguments.of(ExecutionState.FAILURE, ExecutionState.PENDING),
+                Arguments.of(ExecutionState.RUNNING, ExecutionState.RESTART),
+                Arguments.of(ExecutionState.RESTART, ExecutionState.RESTART)
             )
     }
 
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
index 77a3986f1e078c9b2557a9b4b0a19335a8267ab2..adddc705616935e5440c1c601615ce9a065df4c4 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt
@@ -12,7 +12,7 @@ import org.junit.jupiter.params.provider.Arguments
 import org.junit.jupiter.params.provider.MethodSource
 import org.mockito.kotlin.*
 import theodolite.model.crd.ExecutionCRD
-import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionState
 import java.io.FileInputStream
 import java.util.concurrent.CountDownLatch
 import java.util.stream.Stream
@@ -104,7 +104,7 @@ class ExecutionEventHandlerTestWithInformer {
 
         // Await informer called
         this.addCountDownLatch.await()
-        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.PENDING, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
@@ -123,16 +123,16 @@ class ExecutionEventHandlerTestWithInformer {
         val execution = executionResource.create()
 
         // Update status of execution
-        execution.status.executionState = ExecutionStates.RUNNING.value
+        execution.status.executionState = ExecutionState.RUNNING
         executionResource.patchStatus(execution)
 
         // Assert that status at server matches set status
-        // assertEquals(ExecutionStates.RUNNING.value, this.executionClient.withName(executionName).get().status.executionState)
+        // assertEquals(ExecutionStates.RUNNING, this.executionClient.withName(executionName).get().status.executionState)
 
         // Await informer called
         this.addCountDownLatch.await()
         verify(this.controller).stop(true)
-        assertEquals(ExecutionStates.RESTART.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.RESTART, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
@@ -149,7 +149,7 @@ class ExecutionEventHandlerTestWithInformer {
         // Get execution from server
         val firstExecutionResponse = this.executionClient.withName(executionName).get()
         // Assert that execution at server has pending status
-        assertEquals(ExecutionStates.PENDING.value, firstExecutionResponse.status.executionState)
+        assertEquals(ExecutionState.PENDING, firstExecutionResponse.status.executionState)
 
         // Create new version of execution and update at server
         getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
@@ -157,20 +157,20 @@ class ExecutionEventHandlerTestWithInformer {
         // Await informer called
         this.updateCountDownLatch.await()
         // Get execution from server and assert that new status matches expected one
-        assertEquals(ExecutionStates.PENDING.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(ExecutionState.PENDING, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @ParameterizedTest
     @MethodSource("provideOnUpdateTestArguments")
     @DisplayName("Test onUpdate method for execution with different status")
-    fun testOnUpdateWithStatus(beforeState: ExecutionStates, expectedState: ExecutionStates) {
+    fun testOnUpdateWithStatus(beforeState: ExecutionState, expectedState: ExecutionState) {
         // Create first version of execution resource
         val firstExecutionResource = getExecutionFromSystemResource("k8s-resource-files/test-execution.yaml")
         val firstExecution = firstExecutionResource.create()
         val executionName = firstExecution.metadata.name
 
         // Update status of execution
-        firstExecution.status.executionState = beforeState.value
+        firstExecution.status.executionState = beforeState
         firstExecutionResource.patchStatus(firstExecution)
 
         // Start informer
@@ -179,7 +179,7 @@ class ExecutionEventHandlerTestWithInformer {
         // Get execution from server
         val firstExecutionResponse = this.executionClient.withName(executionName).get()
         // Assert that status at server matches set status
-        assertEquals(beforeState.value, firstExecutionResponse.status.executionState)
+        assertEquals(beforeState, firstExecutionResponse.status.executionState)
 
         // Create new version of execution and update at server
         getExecutionFromSystemResource("k8s-resource-files/test-execution-update.yaml").createOrReplace()
@@ -187,7 +187,7 @@ class ExecutionEventHandlerTestWithInformer {
         // Await informer called
         this.updateCountDownLatch.await()
         // Get execution from server and assert that new status matches expected one
-        assertEquals(expectedState.value, this.executionClient.withName(executionName).get().status.executionState)
+        assertEquals(expectedState, this.executionClient.withName(executionName).get().status.executionState)
     }
 
     @Test
@@ -199,7 +199,7 @@ class ExecutionEventHandlerTestWithInformer {
         val executionName = firstExecution.metadata.name
 
         // Update status of execution to be running
-        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecution.status.executionState = ExecutionState.RUNNING
         firstExecutionResource.patchStatus(firstExecution)
 
         // Get execution from server
@@ -235,7 +235,7 @@ class ExecutionEventHandlerTestWithInformer {
         val executionName = firstExecution.metadata.name
 
         // Update status of execution to be running
-        firstExecution.status.executionState = ExecutionStates.RUNNING.value
+        firstExecution.status.executionState = ExecutionState.RUNNING
         firstExecutionResource.patchStatus(firstExecution)
 
         // Get execution from server
@@ -272,11 +272,11 @@ class ExecutionEventHandlerTestWithInformer {
         fun provideOnUpdateTestArguments(): Stream<Arguments> =
             Stream.of(
                 // before state -> expected state
-                Arguments.of(ExecutionStates.PENDING, ExecutionStates.PENDING),
-                Arguments.of(ExecutionStates.FINISHED, ExecutionStates.PENDING),
-                Arguments.of(ExecutionStates.FAILURE, ExecutionStates.PENDING),
+                Arguments.of(ExecutionState.PENDING, ExecutionState.PENDING),
+                Arguments.of(ExecutionState.FINISHED, ExecutionState.PENDING),
+                Arguments.of(ExecutionState.FAILURE, ExecutionState.PENDING),
                 // Arguments.of(ExecutionStates.RUNNING, ExecutionStates.RESTART), // see testOnDeleteWithExecutionRunning
-                Arguments.of(ExecutionStates.RESTART, ExecutionStates.RESTART)
+                Arguments.of(ExecutionState.RESTART, ExecutionState.RESTART)
             )
     }
 
diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
index 44b6fce2796222d33c7f49091e4b61c79da770b8..138f79eadc6bdee17e62cc7a961eb7de539fa3df 100644
--- a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt
@@ -12,11 +12,11 @@ import org.junit.jupiter.api.DisplayName
 import org.junit.jupiter.api.Test
 import theodolite.k8s.K8sManager
 import theodolite.k8s.resourceLoader.K8sResourceLoaderFromFile
-import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionState
 import java.time.Duration
 
-@WithKubernetesTestServer
 @QuarkusTest
+@WithKubernetesTestServer
 class StateHandlerTest {
     private val testResourcePath = "./src/test/resources/k8s-resource-files/"
 
@@ -54,14 +54,7 @@ class StateHandlerTest {
     @DisplayName("Test empty execution state")
     fun executionWithoutExecutionStatusTest() {
         val handler = ExecutionStateHandler(client = server.client)
-        assertEquals(ExecutionStates.NO_STATE, handler.getExecutionState("example-execution"))
-    }
-
-    @Test
-    @DisplayName("Test empty duration state")
-    fun executionWithoutDurationStatusTest() {
-        val handler = ExecutionStateHandler(client = server.client)
-        assertEquals("-", handler.getDurationState("example-execution"))
+        assertEquals(ExecutionState.NO_STATE, handler.getExecutionState("example-execution"))
     }
 
     @Test
@@ -69,16 +62,8 @@ class StateHandlerTest {
     fun executionStatusTest() {
         val handler = ExecutionStateHandler(client = server.client)
 
-        assertTrue(handler.setExecutionState("example-execution", ExecutionStates.INTERRUPTED))
-        assertEquals(ExecutionStates.INTERRUPTED, handler.getExecutionState("example-execution"))
+        assertTrue(handler.setExecutionState("example-execution", ExecutionState.INTERRUPTED))
+        assertEquals(ExecutionState.INTERRUPTED, handler.getExecutionState("example-execution"))
     }
 
-    @Test
-    @DisplayName("Test set and get of the duration state")
-    fun durationStatusTest() {
-        val handler = ExecutionStateHandler(client = server.client)
-
-        assertTrue(handler.setDurationState("example-execution", Duration.ofMillis(100)))
-        assertEquals("0s", handler.getDurationState("example-execution"))
-    }
 }
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt b/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..157bc1c03cc40375c928677189f549052e1e134d
--- /dev/null
+++ b/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt
@@ -0,0 +1,144 @@
+package theodolite.model.crd
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.exc.InvalidFormatException
+import io.fabric8.kubernetes.api.model.MicroTime
+import io.fabric8.kubernetes.api.model.Duration as K8sDuration
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.time.Clock
+import java.time.Duration
+import java.time.Instant
+import java.time.ZoneId
+
+
+internal class ExecutionStatusTest {
+
+    @Test
+    fun testDefaultStateSerialization() {
+        val objectMapper = ObjectMapper()
+        val executionStatus = ExecutionStatus()
+        val jsonString = objectMapper.writeValueAsString(executionStatus)
+        val json = objectMapper.readTree(jsonString)
+        val jsonField = json.get("executionState")
+        assertTrue(jsonField.isTextual)
+        assertEquals(ExecutionState.NO_STATE.value, json.get("executionState").asText())
+    }
+
+    @Test
+    fun testCustomStateSerialization() {
+        val objectMapper = ObjectMapper()
+        val executionStatus = ExecutionStatus()
+        executionStatus.executionState = ExecutionState.PENDING
+        val jsonString = objectMapper.writeValueAsString(executionStatus)
+        val json = objectMapper.readTree(jsonString)
+        val jsonField = json.get("executionState")
+        assertTrue(jsonField.isTextual)
+        assertEquals(ExecutionState.PENDING.value, json.get("executionState").asText())
+    }
+
+    @Test
+    fun testStateDeserialization() {
+        val objectMapper = ObjectMapper()
+        val json = objectMapper.createObjectNode()
+        json.put("executionState", ExecutionState.RUNNING.value)
+        json.put("executionDuration", "")
+        val jsonString = objectMapper.writeValueAsString(json)
+        val executionStatus = objectMapper.readValue(jsonString, ExecutionStatus::class.java)
+        val executionState =  executionStatus.executionState
+        assertNotNull(executionState)
+        assertEquals(ExecutionState.RUNNING, executionState)
+    }
+
+    @Test
+    fun testInvalidStateDeserialization() {
+        val objectMapper = ObjectMapper()
+        val json = objectMapper.createObjectNode()
+        json.put("executionState", "invalid-state")
+        json.put("executionDuration", "")
+        val jsonString = objectMapper.writeValueAsString(json)
+        assertThrows<InvalidFormatException> {
+            objectMapper.readValue(jsonString, ExecutionStatus::class.java)
+        }
+    }
+
+    @Test
+    fun `test duration for no start and completion time`() {
+        val executionStatus = ExecutionStatus()
+        assertNull(executionStatus.startTime)
+        assertNull(executionStatus.completionTime)
+        assertNull(executionStatus.executionDuration)
+    }
+
+    @Test
+    fun `test duration for no start but completion time`() {
+        val executionStatus = ExecutionStatus()
+        executionStatus.completionTime = MicroTime(Instant.parse("2022-01-02T18:59:20.492103Z").toString())
+        assertNull(executionStatus.startTime)
+        assertNull(executionStatus.executionDuration)
+    }
+
+    @Test
+    fun `test duration for non completed execution`() {
+        val startInstant = Instant.parse("2022-01-02T18:59:20.492103Z")
+        val sinceStart = Duration.ofMinutes(5)
+        val executionStatus = ExecutionStatus(clock = Clock.fixed(startInstant.plus(sinceStart), ZoneId.systemDefault()))
+        executionStatus.startTime = MicroTime(startInstant.toString())
+        assertNotNull(executionStatus.executionDuration)
+        assertEquals(K8sDuration(sinceStart), executionStatus.executionDuration)
+    }
+
+    @Test
+    fun `test duration for completed execution`() {
+        val startInstant = Instant.parse("2022-01-02T18:59:20.492103Z")
+        val sinceStart = Duration.ofMinutes(5)
+        val executionStatus = ExecutionStatus()
+        executionStatus.startTime = MicroTime(startInstant.toString())
+        executionStatus.completionTime = MicroTime(startInstant.plus(sinceStart).toString())
+        assertNotNull(executionStatus.executionDuration)
+        assertEquals(K8sDuration(sinceStart), executionStatus.executionDuration)
+    }
+
+    @Test
+    fun testDurationSerialization() {
+        val objectMapper = ObjectMapper()
+        val executionStatus = ExecutionStatus()
+        val startInstant = Instant.parse("2022-01-02T18:59:20.492103Z")
+        executionStatus.startTime = MicroTime(startInstant.toString())
+        executionStatus.completionTime = MicroTime(startInstant.plus(Duration.ofMinutes(15)).toString())
+        val jsonString = objectMapper.writeValueAsString(executionStatus)
+        val json = objectMapper.readTree(jsonString)
+        val jsonField = json.get("executionDuration")
+        assertTrue(jsonField.isTextual)
+        assertEquals("15m", jsonField.asText())
+    }
+
+    @Test
+    fun testNotStartedDurationSerialization() {
+        val objectMapper = ObjectMapper()
+        val executionStatus = ExecutionStatus()
+        val jsonString = objectMapper.writeValueAsString(executionStatus)
+        val json = objectMapper.readTree(jsonString)
+
+        assertTrue(json.get("startTime").isNull)
+        assertTrue(json.get("completionTime").isNull)
+        assertTrue(json.get("executionDuration").isNull)
+    }
+
+    @Test
+    fun testWrongDurationDeserialization() {
+        val startTime = "2022-01-02T18:59:20.492103Z"
+        val completionTime = "2022-01-02T19:14:20.492103Z"
+        val objectMapper = ObjectMapper()
+        val json = objectMapper.createObjectNode()
+        json.put("executionState", ExecutionState.RUNNING.value)
+        json.put("executionDuration", "20m")
+        json.put("startTime", startTime)
+        json.put("completionTime", completionTime)
+        val jsonString = objectMapper.writeValueAsString(json)
+        val executionStatus = objectMapper.readValue(jsonString, ExecutionStatus::class.java)
+        assertNotNull(executionStatus.executionDuration)
+        assertEquals(Duration.ofMinutes(15), executionStatus.executionDuration?.duration)
+    }
+}
\ No newline at end of file
diff --git a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt b/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
index 5d50514857a7a206a64a0612c2270936fe01aa3b..ae80312afd2c128f0f542306a8ffda7f3f53876b 100644
--- a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt
@@ -4,7 +4,7 @@ import io.quarkus.test.junit.QuarkusTest
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
 import theodolite.execution.operator.ExecutionCRDummy
-import theodolite.model.crd.ExecutionStates
+import theodolite.model.crd.ExecutionState
 
 
 @QuarkusTest
@@ -12,11 +12,11 @@ class ExecutionStateComparatorTest {
 
     @Test
     fun testCompare() {
-        val comparator = ExecutionStateComparator(ExecutionStates.RESTART)
+        val comparator = ExecutionStateComparator(ExecutionState.RESTART)
         val execution1 = ExecutionCRDummy("dummy1", "default-benchmark")
         val execution2 = ExecutionCRDummy("dummy2", "default-benchmark")
-        execution1.getStatus().executionState = ExecutionStates.RESTART.value
-        execution2.getStatus().executionState = ExecutionStates.PENDING.value
+        execution1.getStatus().executionState = ExecutionState.RESTART
+        execution2.getStatus().executionState = ExecutionState.PENDING
         val list = listOf(execution2.getCR(), execution1.getCR())
 
         assertEquals(