diff --git a/include/aidge/operator/Identity.hpp b/include/aidge/operator/Identity.hpp
index 3059411fd1ddad65212d41fd46a797b28c710090..24476f231806bf38ae48b9e2d5ec405e072afdb2 100644
--- a/include/aidge/operator/Identity.hpp
+++ b/include/aidge/operator/Identity.hpp
@@ -26,6 +26,11 @@
 #include "aidge/utils/ErrorHandling.hpp"
 
 namespace Aidge {
+class Identity_OpImpl : public OperatorImpl {
+public:
+    Identity_OpImpl(const Operator& op, const std::string& backend = ""): OperatorImpl(op, backend) {}
+    void forward() override;
+};
 
 /**
  * @brief Indentity_Op is an helper operator made to ease the declaration of MetaNodes.
@@ -54,30 +59,8 @@ public:
      */
     std::shared_ptr<Operator> clone() const override;
 
-    // bool forwardDims(bool /*allowDataDependency*/ = false) override final { return true; } // Do nothing
-
-    /**
-     * @brief Check if output dimensions have been computed.
-     * @note Since Indentity has no output Tensor, this function checks if its
-     * only input's dimensions have been computed.
-     *
-     * @return true Input has dimensions.
-     * @return false Input has no dimensions or is a nullptr.
-     */
-    bool dimsForwarded() const override final;
-
-
-    void forward() override final;
-
-    void backward() override final { }
-
-    void setBackend(const std::string& /*name*/, DeviceIdx_t /*device*/ = 0) override final {
-        // setBackend do nothing, Identity node has no backend it just pass the same Tensor
-    }
-    std::set<std::string> getAvailableBackends() const override { return std::set<std::string>(); };
-    void setDataType(const DataType& /*dataType*/) const override final {
-        // setDatatype do nothing, Identity node has no backend it just pass the same Tensor
-    }
+    void setBackend(const std::string& name, DeviceIdx_t device = 0) override final;
+    std::set<std::string> getAvailableBackends() const override;
 
     static const std::vector<std::string> getInputsName(){
         return {"data_input"};
diff --git a/src/operator/Identity.cpp b/src/operator/Identity.cpp
index 2f60eb2fd9c5d43c60ae7ee3af49c3b2e407a1fe..f0b8720bc1e22d8d6308460eabe436db8a4c9f6d 100644
--- a/src/operator/Identity.cpp
+++ b/src/operator/Identity.cpp
@@ -13,35 +13,37 @@
 
 #include "aidge/operator/Identity.hpp"
 
+void Aidge::Identity_OpImpl::forward() {
+    const Identity_Op& op = dynamic_cast<const Identity_Op&>(mOp);
+    op.getOutput(0)->getImpl()->copy(op.getInput(0)->getImpl()->rawPtr(), op.getInput(0)->size());
+}
+
+//////////////////////////////////////////////////
+
 const std::string Aidge::Identity_Op::Type = "Identity";
 
 Aidge::Identity_Op::Identity_Op()
     : OperatorTensor(Type, {InputCategory::Data}, 1)
 {
-    mImpl = std::make_shared<OperatorImpl>(*this);
+    mImpl = std::make_shared<Identity_OpImpl>(*this);
 }
 
 Aidge::Identity_Op::Identity_Op(const Aidge::Identity_Op& op)
     : OperatorTensor(op)
 {
-    mImpl = std::make_shared<OperatorImpl>(*this, op.backend());
+    mImpl = std::make_shared<Identity_OpImpl>(*this, op.backend());
 }
 
 std::shared_ptr<Aidge::Operator> Aidge::Identity_Op::clone() const {
     return std::make_shared<Identity_Op>(*this);
 }
 
-bool Aidge::Identity_Op::dimsForwarded() const {
-    const auto& input0 = getInput(0);
-    return input0 ? (input0->undefined() ? false :
-                            input0->dims() == getOutput(0)->dims()) :
-                                false;
+void Aidge::Identity_Op::setBackend(const std::string& name, DeviceIdx_t device) {
+    mOutputs[0]->setBackend(name, device);
 }
 
-void Aidge::Identity_Op::forward() {
-    // Perform a shallow copy
-    *(mOutputs[0]) = *(mInputs[0]);
-    runHooks();
+std::set<std::string> Aidge::Identity_Op::getAvailableBackends() const {
+    return Registrar<Identity_Op>::getKeys();
 }
 
 std::shared_ptr<Aidge::Node> Aidge::Identity(const std::string& name) {