diff --git a/ProcessLib/BoundaryCondition/BoundaryCondition.cpp b/ProcessLib/BoundaryCondition/BoundaryCondition.cpp
deleted file mode 100644
index 389f371d8c499b9d8e98a8f575e9fd160f66d158..0000000000000000000000000000000000000000
--- a/ProcessLib/BoundaryCondition/BoundaryCondition.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
- *            Distributed under a Modified BSD License.
- *              See accompanying file LICENSE.txt or
- *              http://www.opengeosys.org/project/license
- *
- */
-
-#include "BoundaryCondition.h"
-#include "BoundaryConditionConfig.h"
-#include "DirichletBoundaryCondition.h"
-#include "ConstraintDirichletBoundaryCondition.h"
-#include "NeumannBoundaryCondition.h"
-#include "NonuniformDirichletBoundaryCondition.h"
-#include "NonuniformNeumannBoundaryCondition.h"
-#include "NormalTractionBoundaryCondition.h"
-#include "PhaseFieldIrreversibleDamageOracleBoundaryCondition.h"
-#include "ProcessLib/Process.h"
-#include "RobinBoundaryCondition.h"
-
-namespace ProcessLib
-{
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned integration_order,
-    const unsigned shapefunction_order,
-    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters,
-    Process const& process)
-{
-    //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type}
-    auto const type = config.config.peekConfigParameter<std::string>("type");
-
-    if (type == "ConstraintDirichlet")
-    {
-        return createConstraintDirichletBoundaryCondition(
-            config, dof_table, mesh, variable_id, integration_order,
-            parameters, process);
-    }
-    if (type == "Dirichlet")
-    {
-        return createDirichletBoundaryCondition(
-                    config, dof_table, mesh, variable_id,
-                    integration_order, shapefunction_order, parameters);
-    }
-    if (type == "Neumann")
-    {
-        return createNeumannBoundaryCondition(
-                    config, dof_table, mesh, variable_id,
-                    integration_order, shapefunction_order, parameters);
-    }
-    if (type == "Robin")
-    {
-        return createRobinBoundaryCondition(
-                    config, dof_table, mesh, variable_id,
-                    integration_order, shapefunction_order, parameters);
-    }
-    if (type == "NonuniformDirichlet")
-    {
-        return createNonuniformDirichletBoundaryCondition(config, dof_table,
-                                                          mesh, variable_id);
-    }
-    if (type == "NonuniformNeumann")
-    {
-        return createNonuniformNeumannBoundaryCondition(
-            config, dof_table, mesh, variable_id, integration_order,
-            shapefunction_order);
-    }
-    //
-    // Special boundary conditions
-    //
-    if (type == "NormalTraction")
-    {
-        return createNormalTractionBoundaryCondition(
-            config, dof_table, mesh, variable_id, integration_order,
-            shapefunction_order, parameters);
-    }
-    if (type == "PhaseFieldIrreversibleDamageOracleBoundaryCondition")
-    {
-        return createPhaseFieldIrreversibleDamageOracleBoundaryCondition(
-            config, dof_table, mesh, variable_id, integration_order,
-            shapefunction_order, parameters);
-    }
-    OGS_FATAL("Unknown boundary condition type: `%s'.", type.c_str());
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createDirichletBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned /*integration_order*/,
-    const unsigned /*shapefunction_order*/,
-    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters)
-{
-    return ProcessLib::createDirichletBoundaryCondition(
-        config.config, config.mesh, dof_table, mesh.getID(), variable_id,
-        *config.component_id, parameters);
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createConstraintDirichletBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned integration_order,
-    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters,
-    Process const& process)
-{
-    return ProcessLib::createConstraintDirichletBoundaryCondition(
-        config.config, config.mesh, dof_table, variable_id, integration_order,
-        *config.component_id, parameters, process);
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createNeumannBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned integration_order,
-    const unsigned shapefunction_order,
-    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters)
-{
-    return ProcessLib::createNeumannBoundaryCondition(
-        config.config, config.mesh, dof_table, variable_id,
-        *config.component_id, mesh.isAxiallySymmetric(), integration_order,
-        shapefunction_order, mesh.getDimension(), parameters);
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createRobinBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned integration_order,
-    const unsigned shapefunction_order,
-    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters)
-{
-    return ProcessLib::createRobinBoundaryCondition(
-        config.config, config.mesh, dof_table, variable_id,
-        *config.component_id, mesh.isAxiallySymmetric(), integration_order,
-        shapefunction_order, mesh.getDimension(), parameters);
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createNonuniformDirichletBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id)
-{
-    return ProcessLib::createNonuniformDirichletBoundaryCondition(
-        config.config, dof_table, variable_id, *config.component_id, mesh);
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createNonuniformNeumannBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned integration_order,
-    const unsigned shapefunction_order)
-{
-    return ProcessLib::createNonuniformNeumannBoundaryCondition(
-        config.config, dof_table, variable_id, *config.component_id,
-        integration_order, shapefunction_order, mesh);
-}
-
-std::unique_ptr<BoundaryCondition>
-BoundaryConditionBuilder::createNormalTractionBoundaryCondition(
-    const BoundaryConditionConfig& config,
-    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
-    const int variable_id, const unsigned integration_order,
-    const unsigned shapefunction_order,
-    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters)
-{
-    return ProcessLib::NormalTractionBoundaryCondition::
-        createNormalTractionBoundaryCondition(
-            config.config, config.mesh, dof_table, variable_id,
-            mesh.isAxiallySymmetric(), integration_order, shapefunction_order,
-            mesh.getDimension(), parameters);
-}
-
-std::unique_ptr<BoundaryCondition> BoundaryConditionBuilder::
-    createPhaseFieldIrreversibleDamageOracleBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned /*integration_order*/,
-        const unsigned /*shapefunction_order*/,
-        const std::vector<
-            std::unique_ptr<ProcessLib::ParameterBase>>& /*parameters*/)
-{
-    return ProcessLib::
-        createPhaseFieldIrreversibleDamageOracleBoundaryCondition(
-            config.config, dof_table, mesh, variable_id, *config.component_id);
-}
-
-}  // namespace ProcessLib
diff --git a/ProcessLib/BoundaryCondition/BoundaryCondition.h b/ProcessLib/BoundaryCondition/BoundaryCondition.h
index 43fc1db7f3816bec3e1ac2ab0f863e7cc91d7aa3..f20c2ced8db05f9f4f5fd2565e2ba9fd8d6308fd 100644
--- a/ProcessLib/BoundaryCondition/BoundaryCondition.h
+++ b/ProcessLib/BoundaryCondition/BoundaryCondition.h
@@ -58,87 +58,4 @@ public:
     virtual ~BoundaryCondition() = default;
 };
 
-class BoundaryConditionBuilder
-{
-public:
-    virtual ~BoundaryConditionBuilder() = default;
-
-    virtual std::unique_ptr<BoundaryCondition> createBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order, const unsigned shapefunction_order,
-        const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>&
-            parameters,
-        Process const& process);
-
-protected:
-    virtual std::unique_ptr<BoundaryCondition> createDirichletBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order,
-        const unsigned shapefunction_order,
-        const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>&
-            parameters);
-
-    virtual std::unique_ptr<BoundaryCondition>
-    createConstraintDirichletBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order,
-        const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>&
-            parameters,
-        Process const& process);
-
-    virtual std::unique_ptr<BoundaryCondition> createNeumannBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order, const unsigned shapefunction_order,
-        const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>&
-            parameters);
-
-    virtual std::unique_ptr<BoundaryCondition> createRobinBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order, const unsigned shapefunction_order,
-        const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>&
-            parameters);
-
-    virtual std::unique_ptr<BoundaryCondition>
-    createNonuniformDirichletBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id);
-
-    virtual std::unique_ptr<BoundaryCondition>
-    createNonuniformNeumannBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order, const unsigned shapefunction_order);
-
-    virtual std::unique_ptr<BoundaryCondition>
-    createNormalTractionBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned integration_order, const unsigned shapefunction_order,
-        const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>&
-            parameters);
-
-    virtual std::unique_ptr<BoundaryCondition>
-    createPhaseFieldIrreversibleDamageOracleBoundaryCondition(
-        const BoundaryConditionConfig& config,
-        const NumLib::LocalToGlobalIndexMap& dof_table,
-        const MeshLib::Mesh& mesh, const int variable_id,
-        const unsigned /*integration_order*/,
-        const unsigned /*shapefunction_order*/,
-        const std::vector<
-            std::unique_ptr<ProcessLib::ParameterBase>>& /*parameters*/);
-};
-
 }  // ProcessLib
diff --git a/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h b/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h
index b511506028c9900542f20d89cc72ae225fb67468..26adc6ae3ee1f781a0047f06ae10aea9f5bc2330 100644
--- a/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h
+++ b/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h
@@ -12,6 +12,8 @@
 #include "NumLib/IndexValueVector.h"
 #include "ProcessLib/ProcessVariable.h"
 
+#include "BoundaryCondition.h"
+
 namespace ProcessLib
 {
 class BoundaryConditionCollection final
diff --git a/ProcessLib/BoundaryCondition/CreateBoundaryCondition.cpp b/ProcessLib/BoundaryCondition/CreateBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35948a821937ebded3d48920295f9fbc5355a08d
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/CreateBoundaryCondition.cpp
@@ -0,0 +1,95 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "CreateBoundaryCondition.h"
+
+#include "BoundaryCondition.h"
+#include "BoundaryConditionConfig.h"
+#include "ConstraintDirichletBoundaryCondition.h"
+#include "DirichletBoundaryCondition.h"
+#include "NeumannBoundaryCondition.h"
+#include "NonuniformDirichletBoundaryCondition.h"
+#include "NonuniformNeumannBoundaryCondition.h"
+#include "NormalTractionBoundaryCondition.h"
+#include "PhaseFieldIrreversibleDamageOracleBoundaryCondition.h"
+#include "RobinBoundaryCondition.h"
+
+namespace ProcessLib
+{
+std::unique_ptr<BoundaryCondition> createBoundaryCondition(
+    const BoundaryConditionConfig& config,
+    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
+    const int variable_id, const unsigned integration_order,
+    const unsigned shapefunction_order,
+    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters,
+    const Process& process)
+{
+    //! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type}
+    auto const type = config.config.peekConfigParameter<std::string>("type");
+
+    if (type == "Dirichlet")
+    {
+        return ProcessLib::createDirichletBoundaryCondition(
+            config.config, config.mesh, dof_table, mesh.getID(), variable_id,
+            *config.component_id, parameters);
+    }
+    if (type == "Neumann")
+    {
+        return ProcessLib::createNeumannBoundaryCondition(
+            config.config, config.mesh, dof_table, variable_id,
+            *config.component_id, mesh.isAxiallySymmetric(), integration_order,
+            shapefunction_order, mesh.getDimension(), parameters);
+    }
+    if (type == "Robin")
+    {
+        return ProcessLib::createRobinBoundaryCondition(
+            config.config, config.mesh, dof_table, variable_id,
+            *config.component_id, mesh.isAxiallySymmetric(), integration_order,
+            shapefunction_order, mesh.getDimension(), parameters);
+    }
+    if (type == "NonuniformDirichlet")
+    {
+        return ProcessLib::createNonuniformDirichletBoundaryCondition(
+            config.config, dof_table, variable_id, *config.component_id, mesh);
+    }
+    if (type == "NonuniformNeumann")
+    {
+        return ProcessLib::createNonuniformNeumannBoundaryCondition(
+            config.config, dof_table, variable_id, *config.component_id,
+            integration_order, shapefunction_order, mesh);
+    }
+
+    //
+    // Special boundary conditions
+    //
+    if (type == "ConstraintDirichlet")
+    {
+        return createConstraintDirichletBoundaryCondition(
+            config.config, config.mesh, dof_table, variable_id,
+            integration_order, *config.component_id, parameters, process);
+    }
+    if (type == "NormalTraction")
+    {
+        return ProcessLib::NormalTractionBoundaryCondition::
+            createNormalTractionBoundaryCondition(
+                config.config, config.mesh, dof_table, variable_id,
+                mesh.isAxiallySymmetric(), integration_order,
+                shapefunction_order, mesh.getDimension(), parameters);
+    }
+    if (type == "PhaseFieldIrreversibleDamageOracleBoundaryCondition")
+    {
+        return ProcessLib::
+            createPhaseFieldIrreversibleDamageOracleBoundaryCondition(
+                config.config, dof_table, mesh, variable_id,
+                *config.component_id);
+    }
+    OGS_FATAL("Unknown boundary condition type: `%s'.", type.c_str());
+}
+
+}  // namespace ProcessLib
diff --git a/ProcessLib/BoundaryCondition/CreateBoundaryCondition.h b/ProcessLib/BoundaryCondition/CreateBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..97478a17d2ccef2d057d9778ffbe13827df352af
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/CreateBoundaryCondition.h
@@ -0,0 +1,40 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+namespace MeshLib
+{
+class Mesh;
+}
+
+namespace NumLib
+{
+class LocalToGlobalIndexMap;
+}  // namespace NumLib
+
+namespace ProcessLib
+{
+class BoundaryCondition;
+struct BoundaryConditionConfig;
+struct ParameterBase;
+class Process;
+
+std::unique_ptr<BoundaryCondition> createBoundaryCondition(
+    const BoundaryConditionConfig& config,
+    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
+    const int variable_id, const unsigned integration_order,
+    const unsigned shapefunction_order,
+    const std::vector<std::unique_ptr<ProcessLib::ParameterBase>>& parameters,
+    const Process& process);
+
+}  // namespace ProcessLib
diff --git a/ProcessLib/ProcessVariable.cpp b/ProcessLib/ProcessVariable.cpp
index 87a84d7d38b89b430b700bdb17637cd9c80f7e71..e157087036879b4c2ea08996a6006ea7397dea3f 100644
--- a/ProcessLib/ProcessVariable.cpp
+++ b/ProcessLib/ProcessVariable.cpp
@@ -13,6 +13,8 @@
 #include <logog/include/logog.hpp>
 
 #include "MeshLib/Mesh.h"
+#include "ProcessLib/BoundaryCondition/BoundaryCondition.h"
+#include "ProcessLib/BoundaryCondition/CreateBoundaryCondition.h"
 #include "ProcessLib/Utils/ProcessUtils.h"
 
 namespace ProcessLib
@@ -33,7 +35,6 @@ ProcessVariable::ProcessVariable(
           //! \ogs_file_param{prj__process_variables__process_variable__initial_condition}
           config.getConfigParameter<std::string>("initial_condition"),
           parameters, _n_components)),
-      _bc_builder(std::make_unique<BoundaryConditionBuilder>()),
       _source_term_builder(std::make_unique<SourceTermBuilder>())
 {
     DBUG("Constructing process variable %s", _name.c_str());
@@ -146,7 +147,6 @@ ProcessVariable::ProcessVariable(ProcessVariable&& other)
       _shapefunction_order(other._shapefunction_order),
       _initial_condition(std::move(other._initial_condition)),
       _bc_configs(std::move(other._bc_configs)),
-      _bc_builder(std::move(other._bc_builder)),
       _source_term_configs(std::move(other._source_term_configs)),
       _source_term_builder(std::move(other._source_term_builder))
 {
@@ -181,9 +181,10 @@ ProcessVariable::createBoundaryConditions(
 
     for (auto& config : _bc_configs)
     {
-        auto bc = _bc_builder->createBoundaryCondition(
-            config, dof_table, _mesh, variable_id, integration_order,
-            _shapefunction_order, parameters, process);
+        auto bc = createBoundaryCondition(config, dof_table, _mesh, variable_id,
+                                          integration_order,
+                                          _shapefunction_order, parameters,
+                                          process);
         bcs.push_back(std::move(bc));
     }
 
diff --git a/ProcessLib/ProcessVariable.h b/ProcessLib/ProcessVariable.h
index 9cd33a18caa6ab1fe2a219235012f80f54518064..6f0fe06414c5832d9f5ce55d77006624fa250b54 100644
--- a/ProcessLib/ProcessVariable.h
+++ b/ProcessLib/ProcessVariable.h
@@ -9,7 +9,6 @@
 
 #pragma once
 
-#include "ProcessLib/BoundaryCondition/BoundaryCondition.h"
 #include "ProcessLib/BoundaryCondition/BoundaryConditionConfig.h"
 #include "ProcessLib/Parameter/Parameter.h"
 #include "ProcessLib/SourceTerms/SourceTermConfig.h"
@@ -20,11 +19,20 @@ namespace MeshLib
 class Mesh;
 template <typename T> class PropertyVector;
 }
+namespace NumLib
+{
+class LocalToGlobalIndexMap;
+}
 
 namespace ProcessLib
 {
-class BoundaryConditionBuilder;
+class NodalSourceTerm;
+class BoundaryCondition;
+class Process;
+}  // namespace ProcessLib
 
+namespace ProcessLib
+{
 /// A named process variable. Its properties includes the mesh, and the initial
 /// and boundary conditions as well as the source terms.
 class ProcessVariable
@@ -45,11 +53,6 @@ public:
     /// Returns the number of components of the process variable.
     int getNumberOfComponents() const { return _n_components; }
 
-    void setBoundaryConditionBuilder(std::unique_ptr<BoundaryConditionBuilder> bc_builder)
-    {
-        _bc_builder = std::move(bc_builder);
-    }
-
     std::vector<std::unique_ptr<BoundaryCondition>> createBoundaryConditions(
         const NumLib::LocalToGlobalIndexMap& dof_table, const int variable_id,
         unsigned const integration_order,
@@ -94,7 +97,6 @@ private:
     Parameter<double> const& _initial_condition;
 
     std::vector<BoundaryConditionConfig> _bc_configs;
-    std::unique_ptr<BoundaryConditionBuilder> _bc_builder;
     std::vector<SourceTermConfig> _source_term_configs;
     std::unique_ptr<SourceTermBuilder> _source_term_builder;
 };