diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt
index 05d021b1bcfb77fa8ffeb0522510d49e39ef501c..d57a28e8bbcf4dc101e4814ecaa0d52fe28c08a9 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/Benchmark.kt
@@ -1,5 +1,8 @@
 package theodolite.benchmark
 
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.Namespaced
+import io.fabric8.kubernetes.client.CustomResource
 import io.quarkus.runtime.annotations.RegisterForReflection
 import theodolite.util.ConfigurationOverride
 import theodolite.util.LoadDimension
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
index 38d0f0389ce92a8720df05e892d11cf4f1ac480a..62ab75898d16ff2732ab6aa5c254ec8f87fb7266 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
@@ -2,8 +2,6 @@ package theodolite.benchmark
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
-import io.fabric8.kubernetes.api.model.Namespaced
-import io.fabric8.kubernetes.client.CustomResource
 import io.quarkus.runtime.annotations.RegisterForReflection
 import theodolite.util.ConfigurationOverride
 import kotlin.properties.Delegates
@@ -26,7 +24,7 @@ import kotlin.properties.Delegates
  */
 @JsonDeserialize
 @RegisterForReflection
-class BenchmarkExecution : CustomResource(), Namespaced {
+class BenchmarkExecution : KubernetesResource {
     var executionId: Int = 0
     lateinit var name: String
     lateinit var benchmark: String
@@ -34,7 +32,7 @@ class BenchmarkExecution : CustomResource(), Namespaced {
     lateinit var resources: ResourceDefinition
     lateinit var slos: List<Slo>
     lateinit var execution: Execution
-    lateinit var configOverrides: List<ConfigurationOverride?>
+    lateinit var configOverrides: MutableList<ConfigurationOverride?>
 
     /**
      * This execution encapsulates the [strategy], the [duration], the [repetitions], and the [restrictions]
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecutionList.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecutionList.kt
deleted file mode 100644
index 50e8967f20aebad880ebd218136749af8e3ea6ee..0000000000000000000000000000000000000000
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecutionList.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package theodolite.benchmark
-
-import io.fabric8.kubernetes.client.CustomResourceList
-
-class BenchmarkExecutionList : CustomResourceList<BenchmarkExecution>()
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
index c89e9e85323d6e51c104b1d34ff1ef9d8d4d60cd..aa9c36ad912437e3b104dccf6ff1f4dea5905946 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt
@@ -1,5 +1,6 @@
 package theodolite.benchmark
 
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.fabric8.kubernetes.api.model.Namespaced
 import io.fabric8.kubernetes.client.CustomResource
@@ -30,16 +31,18 @@ private var DEFAULT_NAMESPACE = "default"
  *  for the deserializing in the [theodolite.execution.operator.TheodoliteOperator].
  * @constructor construct an empty Benchmark.
  */
+@JsonDeserialize
 @RegisterForReflection
-class KubernetesBenchmark : Benchmark, CustomResource(), Namespaced {
+class KubernetesBenchmark: KubernetesResource, Benchmark{
     lateinit var name: String
     lateinit var appResource: List<String>
     lateinit var loadGenResource: List<String>
     lateinit var resourceTypes: List<TypeName>
     lateinit var loadTypes: List<TypeName>
     lateinit var kafkaConfig: KafkaConfig
-    private val namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
-    var path = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config"
+    var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE
+    var path =  System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config"
+
 
     /**
      * Loads [KubernetesResource]s.
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkList.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkList.kt
deleted file mode 100644
index 0930875e96146fda58301478bda68b00c229e99f..0000000000000000000000000000000000000000
--- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkList.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package theodolite.benchmark
-
-import io.fabric8.kubernetes.client.CustomResourceList
-
-class KubernetesBenchmarkList : CustomResourceList<KubernetesBenchmark>()
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
index ded4943c14ff8250f3dcad5279ff670af5fd7fd3..1fecc4664b02e51b581d84d6cbc19c9ddda82c9a 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
@@ -13,10 +13,6 @@ import theodolite.util.Resource
 import theodolite.util.Results
 import java.io.File
 import java.io.PrintWriter
-import java.lang.IllegalArgumentException
-import java.lang.Thread.sleep
-import java.nio.file.Files
-import java.nio.file.Path
 import java.time.Duration
 
 
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..75cbcad051e2055f25d876e66e0fffcdc249c4f5
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt
@@ -0,0 +1,55 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.api.model.Namespaced
+import io.fabric8.kubernetes.client.CustomResource
+import io.fabric8.kubernetes.client.CustomResourceDoneable
+import io.fabric8.kubernetes.client.CustomResourceList
+import io.fabric8.kubernetes.client.KubernetesClient
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
+import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
+import java.lang.Thread.sleep
+
+abstract class AbstractStateHandler<T,L,D>(
+    private val context: CustomResourceDefinitionContext,
+    private val client: KubernetesClient,
+    private val crd: Class<T>,
+    private val crdList: Class<L>,
+    private val donableCRD: Class<D>
+    ): StateHandler where T : CustomResource, T: Namespaced, L: CustomResourceList<T>, D: CustomResourceDoneable<T> {
+
+    private val crdClient: MixedOperation<T, L, D, Resource<T, D>> =
+        this.client.customResources(this.context, this.crd, this.crdList, this.donableCRD)
+
+    @Synchronized
+    override fun setState(resourceName: String, f: (CustomResource) -> CustomResource?) {
+        this.crdClient
+            .inNamespace(this.client.namespace)
+            .list().items
+            .filter { item -> item.metadata.name == resourceName }
+            .map { customResource -> f(customResource) }
+            .forEach { this.crdClient.updateStatus(it as T) }
+       }
+
+    @Synchronized
+    override fun getState(resourceName: String, f: (CustomResource) -> String?): String? {
+        return this.crdClient
+            .inNamespace(this.client.namespace)
+            .list().items
+            .filter { item -> item.metadata.name == resourceName }
+            .map { customResource -> f(customResource) }
+            .firstOrNull()
+    }
+
+    @Synchronized
+    override fun blockUntilStateIsSet(resourceName: String, desiredStatusString: String, f: (CustomResource) -> String?, maxTries: Int): Boolean {
+        for (i in 0.rangeTo(maxTries)) {
+            val currentStatus = getState(resourceName, f)
+                if(currentStatus == desiredStatusString) {
+                    return true
+                }
+            sleep(50)
+        }
+        return false
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/BenchmarkEventHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/BenchmarkEventHandler.kt
deleted file mode 100644
index 7c8188e3c342cfc1b22fefdd3ca91e7dbce85905..0000000000000000000000000000000000000000
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/BenchmarkEventHandler.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package theodolite.execution.operator
-
-import io.fabric8.kubernetes.client.informers.ResourceEventHandler
-import mu.KotlinLogging
-import theodolite.benchmark.KubernetesBenchmark
-
-private val logger = KotlinLogging.logger {}
-
-/**
- * Handles adding, updating and deleting KubernetesBenchmarks.
- *
- * @param controller The TheodoliteController that handles the application state
- *
- * @see TheodoliteController
- * @see KubernetesBenchmark
- */
-class BenchmarkEventHandler(private val controller: TheodoliteController) : ResourceEventHandler<KubernetesBenchmark> {
-
-    /**
-     * Add a KubernetesBenchmark.
-     *
-     * @param benchmark the KubernetesBenchmark to add
-     *
-     * @see KubernetesBenchmark
-     */
-    override fun onAdd(benchmark: KubernetesBenchmark) {
-        benchmark.name = benchmark.metadata.name
-        logger.info { "Add new benchmark ${benchmark.name}." }
-        this.controller.benchmarks[benchmark.name] = benchmark
-    }
-
-    /**
-     * Update a KubernetesBenchmark.
-     *
-     * @param oldBenchmark the KubernetesBenchmark to update
-     * @param newBenchmark the updated KubernetesBenchmark
-     *
-     * @see KubernetesBenchmark
-     */
-    override fun onUpdate(oldBenchmark: KubernetesBenchmark, newBenchmark: KubernetesBenchmark) {
-        logger.info { "Update benchmark ${newBenchmark.metadata.name}." }
-        newBenchmark.name = newBenchmark.metadata.name
-        if (this.controller.isInitialized() && this.controller.executor.getBenchmark().name == oldBenchmark.metadata.name) {
-            this.controller.isUpdated.set(true)
-            this.controller.executor.executor.run.compareAndSet(true, false)
-        } else {
-            onAdd(newBenchmark)
-        }
-    }
-
-    /**
-     * Delete a KubernetesBenchmark.
-     *
-     * @param benchmark the KubernetesBenchmark to delete
-     *
-     * @see KubernetesBenchmark
-     */
-    override fun onDelete(benchmark: KubernetesBenchmark, b: Boolean) {
-        logger.info { "Delete benchmark ${benchmark.metadata.name}." }
-        this.controller.benchmarks.remove(benchmark.metadata.name)
-        if (this.controller.isInitialized() && this.controller.executor.getBenchmark().name == benchmark.metadata.name) {
-            this.controller.isUpdated.set(true)
-            this.controller.executor.executor.run.compareAndSet(true, false)
-            logger.info { "Current benchmark stopped." }
-        }
-    }
-}
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f3b4e9131a7184962310fe107586757cfb983097
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt
@@ -0,0 +1,76 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
+import mu.KotlinLogging
+import org.json.JSONObject
+import theodolite.execution.Shutdown
+import theodolite.k8s.K8sContextFactory
+import theodolite.model.crd.*
+
+private val logger = KotlinLogging.logger {}
+
+class ClusterSetup(
+    private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, DoneableExecution, Resource<ExecutionCRD, DoneableExecution>>,
+    private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, DoneableBenchmark, Resource<BenchmarkCRD, DoneableBenchmark>>,
+    private val client: NamespacedKubernetesClient
+
+    ) {
+    private val serviceMonitorContext = K8sContextFactory().create(
+        api = "v1",
+        scope = "Namespaced",
+        group = "monitoring.coreos.com",
+        plural = "servicemonitors"
+    )
+
+    fun clearClusterState(){
+        stopRunningExecution()
+        clearByLabel()
+    }
+
+    private fun stopRunningExecution() {
+        executionCRDClient
+            .inNamespace(client.namespace)
+            .list()
+            .items
+            .asSequence()
+            .filter {   it.status.executionState == STATES.Running.value }
+            .forEach { execution ->
+                val benchmark = benchmarkCRDClient
+                    .inNamespace(client.namespace)
+                    .list()
+                    .items
+                    .firstOrNull { it.metadata.name == execution.spec.benchmark }
+
+                if (benchmark != null) {
+                    execution.spec.name = execution.metadata.name
+                    benchmark.spec.name = benchmark.metadata.name
+                    Shutdown(execution.spec, benchmark.spec).start()
+                } else {
+                    logger.error {
+                        "Execution with state ${STATES.Running.value} was found, but no corresponding benchmark. " +
+                                "Could not initialize cluster." }
+                }
+
+
+            }
+        }
+
+    private  fun clearByLabel() {
+        this.client.services().withLabel("app.kubernetes.io/created-by=theodolite").delete()
+        this.client.apps().deployments().withLabel("app.kubernetes.io/created-by=theodolite").delete()
+        this.client.apps().statefulSets().withLabel("app.kubernetes.io/created-by=theodolite").delete()
+        this.client.configMaps().withLabel("app.kubernetes.io/created-by=theodolite").delete()
+
+        val serviceMonitors = JSONObject(
+            this.client.customResource(serviceMonitorContext)
+                .list(client.namespace, mapOf(Pair("app.kubernetes.io/created-by", "theodolite")))
+        )
+            .getJSONArray("items")
+
+        (0 until serviceMonitors.length())
+            .map { serviceMonitors.getJSONObject(it).getJSONObject("metadata").getString("name") }
+            .forEach { this.client.customResource(serviceMonitorContext).delete(client.namespace, it) }
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
index ea62b7b895fce772a1f89019ea4aaac0f3957dc1..2469d0f7c016447b8c49135b907135beec74af63 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt
@@ -1,8 +1,11 @@
 package theodolite.execution.operator
 
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
 import io.fabric8.kubernetes.client.informers.ResourceEventHandler
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
+import theodolite.model.crd.*
 
 private val logger = KotlinLogging.logger {}
 
@@ -14,17 +17,30 @@ private val logger = KotlinLogging.logger {}
  * @see TheodoliteController
  * @see BenchmarkExecution
  */
-class ExecutionHandler(private val controller: TheodoliteController) : ResourceEventHandler<BenchmarkExecution> {
+class ExecutionHandler(
+    private val controller: TheodoliteController,
+    private val stateHandler: ExecutionStateHandler
+) : ResourceEventHandler<ExecutionCRD> {
+    private val gson: Gson = GsonBuilder().enableComplexMapKeySerialization().create()
 
     /**
      * Add an execution to the end of the queue of the TheodoliteController.
      *
-     * @param execution the execution to add
+     * @param ExecutionCRD the execution to add
      */
-    override fun onAdd(execution: BenchmarkExecution) {
-        execution.name = execution.metadata.name
-        logger.info { "Add new execution ${execution.metadata.name} to queue." }
-        this.controller.executionsQueue.add(execution)
+    @Synchronized
+    override fun onAdd(execution: ExecutionCRD) {
+        logger.info { "Add execution ${execution.metadata.name}" }
+        execution.spec.name = execution.metadata.name
+        when (this.stateHandler.getExecutionState(execution.metadata.name)) {
+            null -> this.stateHandler.setExecutionState(execution.spec.name, STATES.Pending)
+            STATES.Running -> {
+                this.stateHandler.setExecutionState(execution.spec.name, STATES.Restart)
+                if(this.controller.isExecutionRunning(execution.spec.name)){
+                    this.controller.stop(restart=true)
+                    }
+                }
+        }
     }
 
     /**
@@ -32,40 +48,39 @@ class ExecutionHandler(private val controller: TheodoliteController) : ResourceE
      * added to the beginning of the queue of the TheodoliteController.
      * Otherwise, it is just added to the beginning of the queue.
      *
-     * @param oldExecution the old execution
-     * @param newExecution the new execution
+     * @param oldExecutionCRD the old execution
+     * @param newExecutionCRD the new execution
      */
-    override fun onUpdate(oldExecution: BenchmarkExecution, newExecution: BenchmarkExecution) {
-        logger.info { "Add updated execution to queue." }
-        newExecution.name = newExecution.metadata.name
-        try {
-            this.controller.executionsQueue.removeIf { e -> e.name == newExecution.metadata.name }
-        } catch (e: NullPointerException) {
-            logger.warn { "No execution found for deletion" }
-        }
-        this.controller.executionsQueue.addFirst(newExecution)
-        if (this.controller.isInitialized() && this.controller.executor.getExecution().name == newExecution.metadata.name) {
-            this.controller.isUpdated.set(true)
-            this.controller.executor.executor.run.compareAndSet(true, false)
+    @Synchronized
+    override fun onUpdate(oldExecution: ExecutionCRD, newExecution: ExecutionCRD) {
+        logger.info { "Receive update event for execution ${oldExecution.metadata.name}" }
+        newExecution.spec.name = newExecution.metadata.name
+        oldExecution.spec.name = oldExecution.metadata.name
+        if(gson.toJson(oldExecution.spec) != gson.toJson(newExecution.spec)) {
+            when(this.stateHandler.getExecutionState(newExecution.metadata.name)) {
+                STATES.Running -> {
+                        this.stateHandler.setExecutionState(newExecution.spec.name, STATES.Restart)
+                         if (this.controller.isExecutionRunning(newExecution.spec.name)){
+                            this.controller.stop(restart=true)
+                            }
+                        }
+                STATES.Restart -> {} // should this set to pending?
+                else -> this.stateHandler.setExecutionState(newExecution.spec.name, STATES.Pending)
+                }
+            }
         }
-    }
 
     /**
      * Delete an execution from the queue of the TheodoliteController.
      *
-     * @param execution the execution to delete
+     * @param ExecutionCRD the execution to delete
      */
-    override fun onDelete(execution: BenchmarkExecution, b: Boolean) {
-        try {
-            this.controller.executionsQueue.removeIf { e -> e.name == execution.metadata.name }
-            logger.info { "Delete execution ${execution.metadata.name} from queue." }
-        } catch (e: NullPointerException) {
-            logger.warn { "No execution found for deletion" }
-        }
-        if (this.controller.isInitialized() && this.controller.executor.getExecution().name == execution.metadata.name) {
-            this.controller.isUpdated.set(true)
-            this.controller.executor.executor.run.compareAndSet(true, false)
-            logger.info { "Current benchmark stopped." }
+    @Synchronized
+    override fun onDelete(execution: ExecutionCRD, b: Boolean) {
+        logger.info { "Delete execution ${execution.metadata.name}" }
+         if(execution.status.executionState == STATES.Running.value
+             && this.controller.isExecutionRunning(execution.spec.name)) {
+            this.controller.stop()
         }
     }
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0e99e92360ef08c389ada40ea30728f118a05adc
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt
@@ -0,0 +1,82 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.CustomResource
+import io.fabric8.kubernetes.client.KubernetesClient
+import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
+import theodolite.model.crd.BenchmarkExecutionList
+import theodolite.model.crd.ExecutionCRD
+import theodolite.model.crd.STATES
+import java.lang.Thread.sleep
+import java.time.Duration
+import java.time.Instant
+import java.util.concurrent.atomic.AtomicBoolean
+
+class ExecutionStateHandler(context: CustomResourceDefinitionContext, val client: KubernetesClient):
+    AbstractStateHandler<ExecutionCRD, BenchmarkExecutionList, DoneableExecution>(
+        context = context,
+        client = client,
+        crd = ExecutionCRD::class.java,
+        crdList = BenchmarkExecutionList::class.java,
+        donableCRD = DoneableExecution::class.java) {
+
+    private var runExecutionDurationTimer: AtomicBoolean = AtomicBoolean(false)
+
+    private fun getExecutionLambda() = { cr: CustomResource ->
+        var execState = ""
+        if (cr is ExecutionCRD) { execState = cr.status.executionState }
+        execState
+    }
+
+    private fun getDurationLambda() = { cr: CustomResource ->
+        var execState = ""
+        if (cr is ExecutionCRD) { execState = cr.status.executionState }
+        execState
+    }
+
+    fun setExecutionState(resourceName: String, status: STATES): Boolean {
+        setState(resourceName) {cr -> if(cr is ExecutionCRD) cr.status.executionState = status.value; cr}
+        return blockUntilStateIsSet(resourceName, status.value, getExecutionLambda())
+    }
+
+    fun getExecutionState(resourceName: String) : STATES? {
+        val status = this.getState(resourceName, getExecutionLambda())
+        return  STATES.values().firstOrNull { it.value == status }
+    }
+
+    fun setDurationState(resourceName: String, duration: Duration) {
+        setState(resourceName) { cr -> if (cr is ExecutionCRD) cr.status.executionDuration = durationToK8sString(duration); cr }
+        blockUntilStateIsSet(resourceName, durationToK8sString(duration), getDurationLambda())
+    }
+
+    fun getDurationState(resourceName: String): String? {
+        return this.getState(resourceName, getDurationLambda())
+    }
+
+    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"
+        }
+    }
+
+    fun startDurationStateTimer(resourceName: String) {
+        this.runExecutionDurationTimer.set(true)
+        val startTime = Instant.now().toEpochMilli()
+        Thread {
+            while (this.runExecutionDurationTimer.get()) {
+                val duration = Duration.ofMillis(Instant.now().minusMillis(startTime).toEpochMilli())
+                setDurationState(resourceName, duration)
+                sleep(100 * 1)
+            }
+        }.start()
+    }
+
+    @Synchronized
+    fun stopDurationStateTimer() {
+        this.runExecutionDurationTimer.set(false)
+        sleep(100 * 2)
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/StateHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0fbd97e5cca4a9be220eb0b0c89ea0af129a7860
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/StateHandler.kt
@@ -0,0 +1,15 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.CustomResource
+private const val MAX_TRIES: Int = 5
+
+interface StateHandler {
+    fun setState(resourceName: String, f: (CustomResource) -> CustomResource?)
+    fun getState(resourceName: String, f: (CustomResource) -> String?): String?
+    fun blockUntilStateIsSet(
+        resourceName: String,
+        desiredStatusString: String,
+        f: (CustomResource) -> String?,
+        maxTries: Int = MAX_TRIES): Boolean
+
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
index 0e889e0393e17fd65f4d8f12c5b95a3dbed7f593..3d76a8620c0112a15d94f0227efcdd5ef9afce1d 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt
@@ -1,122 +1,194 @@
 package theodolite.execution.operator
 
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient
-import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
 import mu.KotlinLogging
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 import theodolite.execution.TheodoliteExecutor
+import theodolite.model.crd.*
+import theodolite.util.ConfigurationOverride
+import theodolite.util.PatcherDefinition
 import java.lang.Thread.sleep
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.ConcurrentLinkedDeque
-import java.util.concurrent.atomic.AtomicBoolean
-import java.util.concurrent.atomic.AtomicInteger
 
 private val logger = KotlinLogging.logger {}
 
 /**
  * The controller implementation for Theodolite.
  *
- * Maintains a Dequeue, based on ConcurrentLinkedDequeue, of executions to be executed for a benchmark.
- *
- * @param client The NamespacedKubernetesClient
- * @param executionContext The CustomResourceDefinitionContext
- *
  * @see NamespacedKubernetesClient
  * @see CustomResourceDefinitionContext
  * @see BenchmarkExecution
  * @see KubernetesBenchmark
  * @see ConcurrentLinkedDeque
  */
+
 class TheodoliteController(
-    val client: NamespacedKubernetesClient,
-    val executionContext: CustomResourceDefinitionContext,
-    val path: String
+    private val namespace: String,
+    val path: String,
+    private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, DoneableExecution, Resource<ExecutionCRD, DoneableExecution>>,
+    private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, DoneableBenchmark, Resource<BenchmarkCRD, DoneableBenchmark>>,
+    private val executionStateHandler: ExecutionStateHandler
 ) {
     lateinit var executor: TheodoliteExecutor
-    val executionsQueue: ConcurrentLinkedDeque<BenchmarkExecution> = ConcurrentLinkedDeque()
-    val benchmarks: ConcurrentHashMap<String, KubernetesBenchmark> = ConcurrentHashMap()
-    var isUpdated = AtomicBoolean(false)
-    var executionID = AtomicInteger(0)
-
     /**
+     *
      * Runs the TheodoliteController forever.
      */
     fun run() {
+        sleep(5000) // wait until all states are correctly set
         while (true) {
-            try {
-                reconcile()
-                logger.info { "Theodolite is waiting for new matching benchmark and execution." }
-                logger.info { "Currently available executions: " }
-                executionsQueue.forEach {
-                    logger.info { "${it.name} : waiting for : ${it.benchmark}" }
-                }
-                logger.info { "Currently available benchmarks: " }
-                benchmarks.forEach {
-                    logger.info { it.key }
-                }
-                sleep(2000)
-            } catch (e: InterruptedException) {
-                logger.error { "Execution interrupted with error: $e." }
-            }
+            reconcile()
+            sleep(2000)
         }
     }
 
-    /**
-     * Ensures that the application state corresponds to the defined KubernetesBenchmarks and BenchmarkExecutions.
-     *
-     * @see KubernetesBenchmark
-     * @see BenchmarkExecution
-     */
-    @Synchronized
     private fun reconcile() {
-        while (executionsQueue.isNotEmpty()) {
-            val execution = executionsQueue.peek()
-            val benchmark = benchmarks[execution.benchmark]
-
-            if (benchmark == null) {
-                logger.debug { "No benchmark found for execution ${execution.name}." }
-                sleep(1000)
+        do {
+            val execution = getNextExecution()
+            if (execution != null) {
+                val benchmark = getBenchmarks()
+                    .firstOrNull { it.name == execution.benchmark }
+                if (benchmark != null) {
+                    runExecution(execution, benchmark)
+                }
             } else {
-                runExecution(execution, benchmark)
+                logger.info { "Could not find executable execution." }
             }
-        }
+        } while (execution != null)
     }
 
     /**
      * Execute a benchmark with a defined KubernetesBenchmark and BenchmarkExecution
      *
-     * @see KubernetesBenchmark
      * @see BenchmarkExecution
      */
-    @Synchronized
-    fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) {
-        execution.executionId = executionID.getAndSet(executionID.get() + 1)
-        isUpdated.set(false)
-        benchmark.path = path
-        logger.info { "Start execution ${execution.name} with benchmark ${benchmark.name}." }
-        executor = TheodoliteExecutor(config = execution, kubernetesBenchmark = benchmark)
-        executor.run()
+    private fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) {
+        setAdditionalLabels(execution.name,
+            "deployed-for-execution",
+            benchmark.appResource + benchmark.loadGenResource,
+            execution)
+        setAdditionalLabels(benchmark.name,
+            "deployed-for-benchmark",
+            benchmark.appResource + benchmark.loadGenResource,
+            execution)
+        setAdditionalLabels("theodolite",
+            "app.kubernetes.io/created-by",
+            benchmark.appResource + benchmark.loadGenResource,
+            execution)
+
+        executionStateHandler.setExecutionState(execution.name, STATES.Running)
+        executionStateHandler.startDurationStateTimer(execution.name)
 
         try {
-            if (!isUpdated.get()) {
-                this.executionsQueue.removeIf { e -> e.name == execution.name }
-                client.customResource(executionContext).delete(client.namespace, execution.metadata.name)
+            executor = TheodoliteExecutor(execution, benchmark)
+            executor.run()
+            when (executionStateHandler.getExecutionState(execution.name)) {
+                STATES.Restart -> runExecution(execution, benchmark)
+                STATES.Running -> {
+                    executionStateHandler.setExecutionState(execution.name, STATES.Finished)
+                    logger.info { "Execution of ${execution.name} is finally stopped." }
+                }
             }
         } catch (e: Exception) {
-            logger.warn { "Deletion skipped." }
+            logger.error { "Failure while executing execution ${execution.name} with benchmark ${benchmark.name}." }
+            logger.error { "Problem is: $e" }
+            executionStateHandler.setExecutionState(execution.name, STATES.Failure)
         }
+        executionStateHandler.stopDurationStateTimer()
+    }
 
-        logger.info { "Execution of ${execution.name} is finally stopped." }
+    @Synchronized
+    fun stop(restart: Boolean = false) {
+        if (!::executor.isInitialized) return
+        if (restart) {
+            executionStateHandler.setExecutionState(this.executor.getExecution().name, STATES.Restart)
+        } else {
+            executionStateHandler.setExecutionState(this.executor.getExecution().name, STATES.Interrupted)
+            logger.warn { "Execution ${executor.getExecution().name} unexpected interrupted" }
+        }
+        this.executor.executor.run.set(false)
+    }
+
+    /**
+     * @return all available [BenchmarkCRD]s
+     */
+    private fun getBenchmarks(): List<KubernetesBenchmark> {
+        return this.benchmarkCRDClient
+            .inNamespace(namespace)
+            .list()
+            .items
+            .map { it.spec.name = it.metadata.name; it }
+            .map { it.spec.path = path; it }
+            .map { it.spec }
     }
 
     /**
-     * @return true if the TheodoliteExecutor of this controller is initialized. Else returns false.
+     * Get the [BenchmarkExecution] for the next run. Which [BenchmarkExecution]
+     * is selected for the next execution depends on three points:
      *
-     * @see TheodoliteExecutor
+     * 1. Only executions are considered for which a matching benchmark is available on the cluster
+     * 2. The Status of the execution must be [STATES.Pending] or [STATES.Restart]
+     * 3. Of the remaining [BenchmarkCRD], those with status [STATES.Restart] are preferred,
+     * then, if there is more than one, the oldest execution is chosen.
+     *
+     * @return the next execution or null
      */
-    @Synchronized
-    fun isInitialized(): Boolean {
-        return ::executor.isInitialized
+    private fun getNextExecution(): BenchmarkExecution? {
+        val availableBenchmarkNames = getBenchmarks()
+            .map { it.name }
+
+        return executionCRDClient
+            .inNamespace(namespace)
+            .list()
+            .items
+            .asSequence()
+            .map { it.spec.name = it.metadata.name; it }
+            .filter {
+                it.status.executionState == STATES.Pending.value ||
+                        it.status.executionState == STATES.Restart.value
+            }
+            .filter { availableBenchmarkNames.contains(it.spec.benchmark) }
+            .sortedWith(stateComparator().thenBy { it.metadata.creationTimestamp })
+            .map { it.spec }
+            .firstOrNull()
+    }
+
+    /**
+     * Simple comparator which can be used to order a list of [ExecutionCRD] such that executions with
+     * status [STATES.Restart] are before all other executions.
+     */
+    private fun stateComparator() = Comparator<ExecutionCRD> { a, b ->
+        when {
+            (a == null && b == null) -> 0
+            (a.status.executionState == STATES.Restart.value) -> -1
+            else -> 1
+        }
+    }
+
+    fun isExecutionRunning(executionName: String): Boolean {
+        return this.executor.getExecution().name == executionName
+    }
+
+    private fun setAdditionalLabels(
+        labelValue: String,
+        labelName: String,
+        resources: List<String>,
+        execution: BenchmarkExecution
+    ) {
+        val additionalConfigOverrides = mutableListOf<ConfigurationOverride>()
+        resources.forEach {
+            run {
+                val configurationOverride = ConfigurationOverride()
+                configurationOverride.patcher = PatcherDefinition()
+                configurationOverride.patcher.type = "LabelPatcher"
+                configurationOverride.patcher.variableName = labelName
+                configurationOverride.patcher.resource = it
+                configurationOverride.value = labelValue
+                additionalConfigOverrides.add(configurationOverride)
+            }
+        }
+        execution.configOverrides.addAll(additionalConfigOverrides)
     }
-}
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
index 5e15a4a80e67f47a42d605d4af39102927139331..49fbf54eecf2a178ae8a0b38bedee1c597a80e1f 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt
@@ -1,13 +1,12 @@
 package theodolite.execution.operator
 
 import io.fabric8.kubernetes.client.DefaultKubernetesClient
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
 import io.fabric8.kubernetes.internal.KubernetesDeserializer
 import mu.KotlinLogging
-import theodolite.benchmark.BenchmarkExecution
-import theodolite.benchmark.BenchmarkExecutionList
-import theodolite.benchmark.KubernetesBenchmark
-import theodolite.benchmark.KubernetesBenchmarkList
 import theodolite.k8s.K8sContextFactory
+import theodolite.model.crd.*
 
 
 private const val DEFAULT_NAMESPACE = "default"
@@ -16,7 +15,7 @@ private const val EXECUTION_SINGULAR = "execution"
 private const val EXECUTION_PLURAL = "executions"
 private const val BENCHMARK_SINGULAR = "benchmark"
 private const val BENCHMARK_PLURAL = "benchmarks"
-private const val API_VERSION = "v1alpha1"
+private const val API_VERSION = "v1"
 private const val RESYNC_PERIOD = 10 * 60 * 1000.toLong()
 private const val GROUP = "theodolite.com"
 private val logger = KotlinLogging.logger {}
@@ -33,42 +32,82 @@ class TheodoliteOperator {
      * Start the operator.
      */
     fun start() {
+        // FIXME("Remove all benchmark state handling")
         logger.info { "Using $namespace as namespace." }
         val client = DefaultKubernetesClient().inNamespace(namespace)
+        client.use {
+            KubernetesDeserializer.registerCustomKind(
+                "$GROUP/$API_VERSION",
+                EXECUTION_SINGULAR,
+                ExecutionCRD::class.java
+            )
 
-        KubernetesDeserializer.registerCustomKind(
-            "$GROUP/$API_VERSION",
-            EXECUTION_SINGULAR,
-            BenchmarkExecution::class.java
-        )
-
-        KubernetesDeserializer.registerCustomKind(
-            "$GROUP/$API_VERSION",
-            BENCHMARK_SINGULAR,
-            KubernetesBenchmark::class.java
-        )
-
-        val contextFactory = K8sContextFactory()
-        val executionContext = contextFactory.create(API_VERSION, SCOPE, GROUP, EXECUTION_PLURAL)
-        val benchmarkContext = contextFactory.create(API_VERSION, SCOPE, GROUP, BENCHMARK_PLURAL)
-
-        val appResource = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config"
-        val controller = TheodoliteController(client = client, executionContext = executionContext, path = appResource)
-
-        val informerFactory = client.informers()
-        val informerExecution = informerFactory.sharedIndexInformerForCustomResource(
-            executionContext, BenchmarkExecution::class.java,
-            BenchmarkExecutionList::class.java, RESYNC_PERIOD
-        )
-        val informerBenchmark = informerFactory.sharedIndexInformerForCustomResource(
-            benchmarkContext, KubernetesBenchmark::class.java,
-            KubernetesBenchmarkList::class.java, RESYNC_PERIOD
-        )
-
-        informerExecution.addEventHandler(ExecutionHandler(controller))
-        informerBenchmark.addEventHandler(BenchmarkEventHandler(controller))
-        informerFactory.startAllRegisteredInformers()
-
-        controller.run()
+            KubernetesDeserializer.registerCustomKind(
+                "$GROUP/$API_VERSION",
+                BENCHMARK_SINGULAR,
+                BenchmarkCRD::class.java
+            )
+
+            val contextFactory = K8sContextFactory()
+            val executionContext = contextFactory.create(API_VERSION, SCOPE, GROUP, EXECUTION_PLURAL)
+            val benchmarkContext = contextFactory.create(API_VERSION, SCOPE, GROUP, BENCHMARK_PLURAL)
+
+            val executionCRDClient: MixedOperation<
+                    ExecutionCRD,
+                    BenchmarkExecutionList,
+                    DoneableExecution,
+                    Resource<ExecutionCRD, DoneableExecution>>
+                = client.customResources(
+                    executionContext,
+                    ExecutionCRD::class.java,
+                    BenchmarkExecutionList::class.java,
+                    DoneableExecution::class.java)
+
+            val benchmarkCRDClient: MixedOperation<
+                    BenchmarkCRD,
+                    KubernetesBenchmarkList,
+                    DoneableBenchmark,
+                    Resource<BenchmarkCRD, DoneableBenchmark>>
+                = client.customResources(
+                    benchmarkContext,
+                    BenchmarkCRD::class.java,
+                    KubernetesBenchmarkList::class.java,
+                    DoneableBenchmark::class.java)
+
+            val executionStateHandler = ExecutionStateHandler(
+                context = executionContext,
+                client = client)
+
+            val appResource = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config"
+            val controller =
+                TheodoliteController(
+                    namespace = client.namespace,
+                    path = appResource,
+                    benchmarkCRDClient = benchmarkCRDClient,
+                    executionCRDClient = executionCRDClient,
+                    executionStateHandler = executionStateHandler)
+
+            val informerFactory = client.informers()
+            val informerExecution = informerFactory.sharedIndexInformerForCustomResource(
+                executionContext,
+                ExecutionCRD::class.java,
+                BenchmarkExecutionList::class.java,
+                RESYNC_PERIOD
+            )
+
+            informerExecution.addEventHandler(ExecutionHandler(
+                controller = controller,
+                stateHandler = executionStateHandler))
+
+            ClusterSetup(
+                executionCRDClient = executionCRDClient,
+                benchmarkCRDClient = benchmarkCRDClient,
+                client = client
+            ).clearClusterState()
+
+            informerFactory.startAllRegisteredInformers()
+            controller.run()
+
+        }
     }
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt
index c58225bf855c70a5a7057132617418a89b0816a8..af9e780d505d7392eff535ee9d3be11780561ce4 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/K8sManager.kt
@@ -63,6 +63,12 @@ class K8sManager(private val client: NamespacedKubernetesClient) {
         }
     }
 
+    fun setLabel(resource: KubernetesResource) {
+        when(resource) {
+            is Deployment -> this.client
+        }
+    }
+
     private fun blockUntilPodsDeleted(podLabel: String) {
         while (!this.client.pods().withLabel(podLabel).list().items.isNullOrEmpty()) {
             logger.info { "Wait for pods with label '$podLabel' to be deleted." }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt
index 4950cee225e103ff095def91de64471ec1894a79..56452d74968db0fd4c939f44f3ed8a7abbe7b928 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/ServiceMonitorWrapper.kt
@@ -53,4 +53,9 @@ class ServiceMonitorWrapper(private val serviceMonitor: Map<String, String>) : C
         val smAsMap = this.serviceMonitor["metadata"]!! as Map<String, String>
         return smAsMap["name"]!!
     }
+
+    fun getLabels(): Map<String, String>{
+        val smAsMap = this.serviceMonitor["metadata"]!! as Map<String, String>
+        return smAsMap["labels"]!! as Map<String, String>
+    }
 }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
new file mode 100644
index 0000000000000000000000000000000000000000..326aa10a21bebd913eaafcb8315188288ae97ff1
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt
@@ -0,0 +1,11 @@
+package theodolite.model.crd
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.Namespaced
+import io.fabric8.kubernetes.client.CustomResource
+import theodolite.benchmark.KubernetesBenchmark
+
+@JsonDeserialize
+class BenchmarkCRD(
+    var spec: KubernetesBenchmark = KubernetesBenchmark()
+) : CustomResource(), Namespaced
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2b2dcc07f9c37f1712109e3d092f2db0c139e1c8
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt
@@ -0,0 +1,5 @@
+package theodolite.model.crd
+
+import io.fabric8.kubernetes.client.CustomResourceList
+
+class BenchmarkExecutionList : CustomResourceList<ExecutionCRD>()
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/DoneableBenchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/DoneableBenchmark.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e00e8268b2ec8eba17b3706feb3940eded1b2b0c
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/DoneableBenchmark.kt
@@ -0,0 +1,7 @@
+package theodolite.model.crd
+
+import io.fabric8.kubernetes.api.builder.Function
+import io.fabric8.kubernetes.client.CustomResourceDoneable
+
+class DoneableBenchmark(resource: BenchmarkCRD, function: Function<BenchmarkCRD, BenchmarkCRD>) :
+    CustomResourceDoneable<BenchmarkCRD>(resource, function)
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/DoneableExecution.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/DoneableExecution.kt
new file mode 100644
index 0000000000000000000000000000000000000000..be07725b405c29a0d9000b6e6ec455536ad111fb
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/DoneableExecution.kt
@@ -0,0 +1,8 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.CustomResourceDoneable
+import io.fabric8.kubernetes.api.builder.Function
+import theodolite.model.crd.ExecutionCRD
+
+class DoneableExecution(resource: ExecutionCRD, function: Function<ExecutionCRD, ExecutionCRD>) :
+    CustomResourceDoneable<ExecutionCRD>(resource, function)
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
new file mode 100644
index 0000000000000000000000000000000000000000..79a387cee250d3abf0fdb576a5f0f33424596792
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt
@@ -0,0 +1,13 @@
+package theodolite.model.crd
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.Namespaced
+import io.fabric8.kubernetes.client.CustomResource
+import theodolite.benchmark.BenchmarkExecution
+
+@JsonDeserialize
+class ExecutionCRD(
+    var spec: BenchmarkExecution = BenchmarkExecution(),
+    var status: ExecutionStatus = ExecutionStatus()
+    ) : CustomResource(), Namespaced
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
new file mode 100644
index 0000000000000000000000000000000000000000..43e9035b3120eb22304576f2006092eec376b6d2
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt
@@ -0,0 +1,13 @@
+package theodolite.model.crd
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.Namespaced
+import io.fabric8.kubernetes.client.CustomResource
+
+@JsonDeserialize
+class ExecutionStatus(): KubernetesResource, CustomResource(), Namespaced {
+    var executionState: String = ""
+    var executionDuration: String = "-"
+
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8ad0a493d948bf5f78741052100766dcf6e316ec
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt
@@ -0,0 +1,5 @@
+package theodolite.model.crd
+
+import io.fabric8.kubernetes.client.CustomResourceList
+
+class KubernetesBenchmarkList : CustomResourceList<BenchmarkCRD>()
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/STATES.kt b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/STATES.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3fcd9751c3ba755121b4b467b45e2cb3f4f13bee
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/model/crd/STATES.kt
@@ -0,0 +1,11 @@
+package theodolite.model.crd
+
+enum class STATES(val value: String) {
+    Running("RUNNING"),
+    Pending("PENDING"),
+    Failure("FAILURE"),
+    Finished("FINISHED"),
+    Restart("RESTART"),
+    Interrupted("INTERRUPTED"),
+    NoState("NoState")
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d9feff00726c8c73483118276eeae7b7975d8c8e
--- /dev/null
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/LabelPatcher.kt
@@ -0,0 +1,50 @@
+package theodolite.patcher
+
+import io.fabric8.kubernetes.api.model.ConfigMap
+import io.fabric8.kubernetes.api.model.KubernetesResource
+import io.fabric8.kubernetes.api.model.Service
+import io.fabric8.kubernetes.api.model.apps.Deployment
+import io.fabric8.kubernetes.api.model.apps.StatefulSet
+import io.fabric8.kubernetes.client.CustomResource
+
+class LabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) :
+    AbstractPatcher(k8sResource, variableName) {
+
+    override fun <String> patch(labelValue: String) {
+        println("call patcher for resource $k8sResource !")
+        if(labelValue is kotlin.String){
+            when(k8sResource){
+                is Deployment -> {
+                    if (k8sResource.metadata.labels == null){
+                        k8sResource.metadata.labels = mutableMapOf()
+                    }
+                    k8sResource.metadata.labels[this.variableName] = labelValue
+                }
+                is StatefulSet -> {
+                    if (k8sResource.metadata.labels == null){
+                        k8sResource.metadata.labels = mutableMapOf()
+                    }
+                    k8sResource.metadata.labels[this.variableName] = labelValue
+                }
+                is Service -> {
+                    if (k8sResource.metadata.labels == null){
+                        k8sResource.metadata.labels = mutableMapOf()
+                    }
+                    k8sResource.metadata.labels[this.variableName] = labelValue
+                }
+                is ConfigMap -> {
+                    if (k8sResource.metadata.labels == null){
+                        k8sResource.metadata.labels = mutableMapOf()
+                    }
+                    k8sResource.metadata.labels[this.variableName] = labelValue
+                }
+                is CustomResource -> {
+                    if (k8sResource.metadata.labels == null){
+                        k8sResource.metadata.labels = mutableMapOf()
+                    }
+                    k8sResource.metadata.labels[this.variableName] = labelValue
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
index 2ee1f6c7b46322cb0f8de03c37aabe64ccf0ba5a..9ca6570ff56a673ffde144b68d3f3d9c90913ef9 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/PatcherFactory.kt
@@ -45,6 +45,7 @@ class PatcherFactory {
                 patcherDefinition.variableName
             )
             "SchedulerNamePatcher" -> SchedulerNamePatcher(resource)
+            "LabelPatcher" -> LabelPatcher(resource, patcherDefinition.variableName)
             else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found")
         }
     }
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt
index 398ff90bed8f48683321e2375458b3a065c39463..4e72ccb0d86749a6538c26556241ac114ef8d9a4 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt
@@ -28,6 +28,7 @@ class KafkaConfig {
      * Wrapper for a topic definition.
      */
     @RegisterForReflection
+    @JsonDeserialize
     class TopicWrapper {
         /**
          * The topic name