diff --git a/theodolite-benchmarks/http-bridge/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/http-bridge/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..a375cb792eeb842ecfd1f789fbf6a716df43e9c8
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,127 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=true
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=true
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_modifiers=false
+cleanup.remove_redundant_semicolons=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=false
+cleanup_profile=_CAU-SE-Style
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_CAU-SE-Style
+formatter_settings_version=21
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=true
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=true
+sp_cleanup.correct_indentation=true
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_modifiers=false
+sp_cleanup.remove_redundant_semicolons=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false
diff --git a/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.checkstyle.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..87860c815222845c1d264d7d0ce498d3397f8280
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.checkstyle.prefs
@@ -0,0 +1,4 @@
+configFilePath=../config/checkstyle.xml
+customModulesJarPaths=
+eclipse.preferences.version=1
+enabled=true
diff --git a/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.pmd.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..efbcb8c9e5d449194a48ca1ea42b7d807b573db9
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/.settings/qa.eclipse.plugin.pmd.prefs
@@ -0,0 +1,4 @@
+customRulesJars=
+eclipse.preferences.version=1
+enabled=true
+ruleSetFilePath=../config/pmd.xml
diff --git a/theodolite-benchmarks/http-bridge/build.gradle b/theodolite-benchmarks/http-bridge/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..0377eefc76b456d8e0f94087b06d0c2689f977cf
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/build.gradle
@@ -0,0 +1,31 @@
+plugins {
+  // common java conventions
+  id 'theodolite.java-conventions'
+
+  // make executable
+  id 'application'
+}
+
+tasks.distZip.enabled = false
+
+repositories {
+  mavenCentral()
+  maven {
+    url "https://oss.sonatype.org/content/repositories/snapshots/"
+  }
+  maven {
+      url 'https://packages.confluent.io/maven/'
+  }
+}
+
+dependencies {
+  implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true }
+  implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true }
+  implementation project(':load-generator-commons')
+  
+  implementation 'io.javalin:javalin:4.3.0'
+  implementation 'com.google.code.gson:gson:2.8.2'
+  runtimeOnly 'org.slf4j:slf4j-simple:1.7.25'
+
+  testImplementation 'junit:junit:4.12'
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..f25c120d2165c4a1f747fdba32de43d4e4d157a6
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Deserializer.java
@@ -0,0 +1,13 @@
+package theodolite.commons.httpbridge;
+
+/**
+ * A class for converting objects to strings.
+ *
+ * @param <T> Type to be deserialized from.
+ */
+@FunctionalInterface
+public interface Deserializer<T> {
+
+  T deserialize(String json);
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..43850d80699a0db0b0fcebd76f625a17f8133f30
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/Endpoint.java
@@ -0,0 +1,52 @@
+package theodolite.commons.httpbridge;
+
+import theodolite.commons.workloadgeneration.RecordSender;
+
+/**
+ * Class describing an endpoint of the {@link HttpBridge}, which converts JSON objects to Java
+ * objects and sends them using a {@link RecordSender}.
+ *
+ * @param <T> Type of objects this endpoint receives and converts.
+ */
+public class Endpoint<T> {
+
+  private final String path;
+
+  private final Deserializer<? extends T> recordDeserializer;
+
+  private final RecordSender<? super T> recordSender;
+
+  /**
+   * Create a new {@link Endpoint} at the given path.
+   */
+  public Endpoint(
+      final String path,
+      final Deserializer<? extends T> recordDeserializer,
+      final RecordSender<? super T> recordSender) {
+    this.path = path;
+    this.recordDeserializer = recordDeserializer;
+    this.recordSender = recordSender;
+  }
+
+  /**
+   * Create a new {@link Endpoint} at the given path with a {@link GsonDeserializer}.
+   */
+  public Endpoint(
+      final String path,
+      final Class<T> recordType,
+      final RecordSender<? super T> recordSender) {
+    this.path = path;
+    this.recordDeserializer = new GsonDeserializer<>(recordType);
+    this.recordSender = recordSender;
+  }
+
+  public String getPath() {
+    return this.path;
+  }
+
+  public void convert(final String json) {
+    final T record = this.recordDeserializer.deserialize(json);
+    this.recordSender.send(record);
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/EnvVarHttpBridgeFactory.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/EnvVarHttpBridgeFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..97956b8d47185c90efdc03393c03c8c44aea2335
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/EnvVarHttpBridgeFactory.java
@@ -0,0 +1,59 @@
+package theodolite.commons.httpbridge;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import theodolite.commons.workloadgeneration.ConfigurationKeys;
+import theodolite.commons.workloadgeneration.TitanKafkaSenderFactory;
+import titan.ccp.model.records.ActivePowerRecord;
+
+class EnvVarHttpBridgeFactory {
+
+  private static final String PORT_KEY = "PORT";
+  private static final int PORT_DEFAULT = 8080;
+
+  private static final String HOST_KEY = "HOST";
+  private static final String HOST_DEFAULT = "0.0.0.0"; // NOPMD
+
+  private static final String KAFKA_BOOTSTRAP_SERVERS_DEFAULT = "localhost:9092"; // NOPMD
+  private static final String KAFKA_TOPIC_DEFAULT = "input";
+  private static final String SCHEMA_REGISTRY_URL_DEFAULT = "http://localhost:8081";
+
+  public HttpBridge create() {
+    final Endpoint<?> converter = new Endpoint<>(
+        "/",
+        ActivePowerRecord.class,
+        TitanKafkaSenderFactory.forKafkaConfig(
+            this.getKafkaBootstrapServer(),
+            this.getKafkaTopic(),
+            this.getSchemaRegistryUrl()));
+    return new HttpBridge(this.getHost(), this.getPort(), List.of(converter));
+  }
+
+  private String getHost() {
+    return Objects.requireNonNullElse(System.getenv(HOST_KEY), HOST_DEFAULT);
+  }
+
+  private int getPort() {
+    return Optional.ofNullable(System.getenv(PORT_KEY)).map(Integer::parseInt).orElse(PORT_DEFAULT);
+  }
+
+  private String getKafkaBootstrapServer() {
+    return Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_BOOTSTRAP_SERVERS),
+        KAFKA_BOOTSTRAP_SERVERS_DEFAULT);
+  }
+
+  private String getKafkaTopic() {
+    return Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.KAFKA_INPUT_TOPIC),
+        KAFKA_TOPIC_DEFAULT);
+  }
+
+  private String getSchemaRegistryUrl() {
+    return Objects.requireNonNullElse(
+        System.getenv(ConfigurationKeys.SCHEMA_REGISTRY_URL),
+        SCHEMA_REGISTRY_URL_DEFAULT);
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/GsonDeserializer.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/GsonDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..42220617546527157d5463d6b9ce9208abc66d58
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/GsonDeserializer.java
@@ -0,0 +1,29 @@
+package theodolite.commons.httpbridge;
+
+import com.google.gson.Gson;
+
+/**
+ * A {@link Deserializer} based on GSON.
+ *
+ * @param <T> Type to be serialized from.
+ */
+public class GsonDeserializer<T> implements Deserializer<T> {
+
+  private final Gson gson;
+  private final Class<T> targetClass;
+
+  public GsonDeserializer(final Class<T> targetClass) {
+    this(new Gson(), targetClass);
+  }
+
+  public GsonDeserializer(final Gson gson, final Class<T> targetClass) {
+    this.gson = gson;
+    this.targetClass = targetClass;
+  }
+
+  @Override
+  public T deserialize(final String json) {
+    return this.gson.fromJson(json, this.targetClass);
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java
new file mode 100644
index 0000000000000000000000000000000000000000..d36e191c8b0a591107de796f511aa853063dff73
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/HttpBridge.java
@@ -0,0 +1,40 @@
+package theodolite.commons.httpbridge;
+
+import java.util.List;
+import theodolite.commons.workloadgeneration.RecordSender;
+
+/**
+ * Class that creates a webserver with potentially multiple {@link Endpoint}s, which receives JSON
+ * objects at these endpoints, converts them to Java objects and send them using
+ * {@link RecordSender}s.
+ */
+public class HttpBridge {
+
+  private final JavalinWebServer webServer;
+
+  public HttpBridge(final String host, final int port, final List<Endpoint<?>> converters) {
+    this.webServer = new JavalinWebServer(converters, host, port);
+  }
+
+  public void start() {
+    this.webServer.start();
+  }
+
+  public void stop() {
+    this.webServer.stop();
+  }
+
+  public void runAsStandalone() {
+    Runtime.getRuntime().addShutdownHook(new Thread(() -> this.stop()));
+    this.start();
+  }
+
+  public static HttpBridge fromEnvironment() {
+    return new EnvVarHttpBridgeFactory().create();
+  }
+
+  public static void main(final String[] args) {
+    HttpBridge.fromEnvironment().runAsStandalone();
+  }
+
+}
diff --git a/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e35172913211d16818228f5df73e1232164a066
--- /dev/null
+++ b/theodolite-benchmarks/http-bridge/src/main/java/theodolite/commons/httpbridge/JavalinWebServer.java
@@ -0,0 +1,47 @@
+package theodolite.commons.httpbridge;
+
+import io.javalin.Javalin;
+import java.util.Collection;
+
+/**
+ * Implementation of a webserver based on the Javalin framework.
+ */
+public class JavalinWebServer {
+
+  private static final int HTTP_SUCCESS = 200;
+
+  private final Javalin app = Javalin.create();
+
+  private final String host;
+  private final int port;
+
+  /**
+   * Create a new instance, running on the specified host and port with the configured endpoints.
+   */
+  public JavalinWebServer(
+      final Collection<Endpoint<?>> converters,
+      final String host,
+      final int port) {
+    this.host = host;
+    this.port = port;
+    this.configureRoutes(converters);
+  }
+
+  private void configureRoutes(final Collection<Endpoint<?>> endpoints) {
+    for (final Endpoint<?> endpoint : endpoints) {
+      this.app.post(endpoint.getPath(), ctx -> {
+        endpoint.convert(ctx.body());
+        ctx.status(HTTP_SUCCESS);
+      });
+    }
+  }
+
+  public void start() {
+    this.app.start(this.host, this.port);
+  }
+
+  public void stop() {
+    this.app.close();
+  }
+
+}
diff --git a/theodolite-benchmarks/settings.gradle b/theodolite-benchmarks/settings.gradle
index ae4254e968a0bc09970752f95c6a40db86ae775c..2f6bd4b74cbf103b740d8d8f57e38ac9deafd3cf 100644
--- a/theodolite-benchmarks/settings.gradle
+++ b/theodolite-benchmarks/settings.gradle
@@ -34,3 +34,4 @@ include 'uc4-flink'
 include 'uc4-beam-flink'
 include 'uc4-beam-samza'
 
+include 'http-bridge'