diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp
index bd01d63daa3225b2d15cf19a1bc1b450cea6b161..6d5d374ea0236f21b67e0664933743e060ac5e21 100644
--- a/source/adios2/core/IO.cpp
+++ b/source/adios2/core/IO.cpp
@@ -155,11 +155,10 @@ bool IO::RemoveVariable(const std::string &name) noexcept
     {                                                                          \
         auto variableMap = GetVariableMap<T>();                                \
         variableMap.erase(index);                                              \
+        isRemoved = true;                                                      \
     }
         ADIOS2_FOREACH_TYPE_1ARG(declare_type)
 #undef declare_type
-
-        isRemoved = true;
     }
 
     if (isRemoved)
@@ -170,6 +169,58 @@ bool IO::RemoveVariable(const std::string &name) noexcept
     return isRemoved;
 }
 
+void IO::RemoveAllVariables() noexcept
+{
+    m_Variables.clear();
+#define declare_type(T) GetVariableMap<T>().clear();
+    ADIOS2_FOREACH_TYPE_1ARG(declare_type)
+#undef declare_type
+    m_Compound.clear();
+}
+
+bool IO::RemoveAttribute(const std::string &name) noexcept
+{
+    bool isRemoved = false;
+    auto itAttribute = m_Attributes.find(name);
+    // attribute exists
+    if (itAttribute != m_Attributes.end())
+    {
+        // first remove the Variable object
+        const std::string type(itAttribute->second.first);
+        const unsigned int index(itAttribute->second.second);
+
+        if (type.empty())
+        {
+            // nothing to do
+        }
+#define declare_type(T)                                                        \
+    else if (type == GetType<T>())                                             \
+    {                                                                          \
+        auto variableMap = GetVariableMap<T>();                                \
+        variableMap.erase(index);                                              \
+        isRemoved = true;                                                      \
+    }
+        ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type)
+#undef declare_type
+    }
+
+    if (isRemoved)
+    {
+        m_Attributes.erase(name);
+    }
+
+    return isRemoved;
+}
+
+void IO::RemoveAllAttributes() noexcept
+{
+    m_Attributes.clear();
+
+#define declare_type(T) GetAttributeMap<T>().clear();
+    ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type)
+#undef declare_type
+}
+
 std::map<std::string, Params> IO::GetAvailableVariables() noexcept
 {
     std::map<std::string, Params> variablesInfo;
diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h
index b7e75c2cef5b78d674f13ccb6e02593dbe2a626f..4bdc2983eff9f78b570a4794c2bf00a6af34f2ea 100644
--- a/source/adios2/core/IO.h
+++ b/source/adios2/core/IO.h
@@ -170,13 +170,29 @@ public:
     Attribute<T> &DefineAttribute(const std::string &name, const T &value);
 
     /**
-     * Removes an existing Variable previously created with DefineVariable
-     * @param name
+     * Removes an existing Variable
+     * @param name unique identifier input
      * @return true: found and removed variable, false: not found, nothing to
      * remove
      */
     bool RemoveVariable(const std::string &name) noexcept;
 
+    /** Removes all existing variables in current IO object */
+    void RemoveAllVariables() noexcept;
+
+    /**
+     * Removes an existing Attribute. Dangerous function since references and
+     * pointers can be dangling after this call.
+     * @param name unique identifier input
+     * @return true: found and removed attribute, false: not found, nothing to
+     * remove
+      */
+    bool RemoveAttribute(const std::string &name) noexcept;
+
+    /** Removes all existing attributes in current IO object. Dangerous function
+     *  since references and pointers can be dangling after this call. */
+    void RemoveAllAttributes() noexcept;
+
     /**
      * Map with variables info: key: name, value: type
      * @return populate map with current variables
@@ -192,6 +208,11 @@ public:
     template <class T>
     Variable<T> *InquireVariable(const std::string &name) noexcept;
 
+    /**
+     * Returns the type of an existing variable as an string
+     * @param name input variable name
+     * @return type
+     */
     std::string InquireVariableType(const std::string &name) const noexcept;
 
     /**
@@ -372,7 +393,7 @@ private:
         noexcept;
 
     /** Checks if attribute exists, called from DefineAttribute different
-     * signatures */
+     *  signatures */
     void CheckAttributeCommon(const std::string &name) const;
 
     /**
diff --git a/testing/adios2/interface/TestADIOSDefineAttribute.cpp b/testing/adios2/interface/TestADIOSDefineAttribute.cpp
index 11559beeca9ddcf881e99975d398839b7df0b960..bc1c1563cc0890cf93ef57d077eca4862d08a72d 100644
--- a/testing/adios2/interface/TestADIOSDefineAttribute.cpp
+++ b/testing/adios2/interface/TestADIOSDefineAttribute.cpp
@@ -540,6 +540,118 @@ TEST_F(ADIOSDefineAttributeTest, GetAttribute)
     }
 }
 
+TEST_F(ADIOSDefineAttributeTest, DefineAndRemove)
+{
+    auto lf_CheckRemove = [&](const std::string variableName) {
+
+        const bool isRemoved = io.RemoveAttribute(variableName);
+        EXPECT_EQ(isRemoved, true);
+    };
+
+    const adios2::Dims shape = {10};
+    const adios2::Dims start = {0};
+    const adios2::Dims count = {10};
+
+    io.DefineAttribute<std::string>("iString", "String Attribute");
+    io.DefineAttribute<int8_t>("i8", -8);
+    io.DefineAttribute<int16_t>("i16", -16);
+    io.DefineAttribute<int32_t>("i32", -32);
+    io.DefineAttribute<int64_t>("i64", -64);
+    io.DefineAttribute<uint8_t>("u8", 8);
+    io.DefineAttribute<uint16_t>("u16", 16);
+    io.DefineAttribute<uint32_t>("u32", 32);
+    io.DefineAttribute<uint64_t>("u64", 64);
+    io.DefineAttribute<float>("r32", 32);
+    io.DefineAttribute<double>("r64", 64);
+
+    lf_CheckRemove("iString");
+    lf_CheckRemove("i8");
+    lf_CheckRemove("i16");
+    lf_CheckRemove("i32");
+    lf_CheckRemove("i64");
+
+    lf_CheckRemove("u8");
+    lf_CheckRemove("u16");
+    lf_CheckRemove("u32");
+    lf_CheckRemove("u64");
+
+    lf_CheckRemove("r32");
+    lf_CheckRemove("r64");
+
+    auto attr_iString = io.InquireAttribute<std::string>("iString");
+    auto attr_i8 = io.InquireAttribute<int8_t>("i8");
+    auto attr_i16 = io.InquireAttribute<int16_t>("i16");
+    auto attr_i32 = io.InquireAttribute<int32_t>("i32");
+    auto attr_i64 = io.InquireAttribute<int64_t>("i64");
+    auto attr_u8 = io.InquireAttribute<uint8_t>("u8");
+    auto attr_u16 = io.InquireAttribute<uint16_t>("u16");
+    auto attr_u32 = io.InquireAttribute<uint32_t>("u32");
+    auto attr_u64 = io.InquireAttribute<uint64_t>("u64");
+    auto attr_r32 = io.InquireAttribute<float>("r32");
+    auto attr_r64 = io.InquireAttribute<double>("r64");
+
+    EXPECT_EQ(attr_iString, nullptr);
+    EXPECT_EQ(attr_i8, nullptr);
+    EXPECT_EQ(attr_i16, nullptr);
+    EXPECT_EQ(attr_i32, nullptr);
+    EXPECT_EQ(attr_i64, nullptr);
+
+    EXPECT_EQ(attr_u8, nullptr);
+    EXPECT_EQ(attr_u16, nullptr);
+    EXPECT_EQ(attr_u32, nullptr);
+    EXPECT_EQ(attr_u64, nullptr);
+
+    EXPECT_EQ(attr_r32, nullptr);
+    EXPECT_EQ(attr_r64, nullptr);
+}
+
+TEST_F(ADIOSDefineAttributeTest, DefineAndRemoveAll)
+{
+    const adios2::Dims shape = {10};
+    const adios2::Dims start = {0};
+    const adios2::Dims count = {10};
+
+    io.DefineAttribute<std::string>("iString", "String Attribute");
+    io.DefineAttribute<int8_t>("i8", -8);
+    io.DefineAttribute<int16_t>("i16", -16);
+    io.DefineAttribute<int32_t>("i32", -32);
+    io.DefineAttribute<int64_t>("i64", -64);
+    io.DefineAttribute<uint8_t>("u8", 8);
+    io.DefineAttribute<uint16_t>("u16", 16);
+    io.DefineAttribute<uint32_t>("u32", 32);
+    io.DefineAttribute<uint64_t>("u64", 64);
+    io.DefineAttribute<float>("r32", 32);
+    io.DefineAttribute<double>("r64", 64);
+
+    io.RemoveAllAttributes();
+
+    auto attr_iString = io.InquireAttribute<std::string>("iString");
+    auto attr_i8 = io.InquireAttribute<int8_t>("i8");
+    auto attr_i16 = io.InquireAttribute<int16_t>("i16");
+    auto attr_i32 = io.InquireAttribute<int32_t>("i32");
+    auto attr_i64 = io.InquireAttribute<int64_t>("i64");
+    auto attr_u8 = io.InquireAttribute<uint8_t>("u8");
+    auto attr_u16 = io.InquireAttribute<uint16_t>("u16");
+    auto attr_u32 = io.InquireAttribute<uint32_t>("u32");
+    auto attr_u64 = io.InquireAttribute<uint64_t>("u64");
+    auto attr_r32 = io.InquireAttribute<float>("r32");
+    auto attr_r64 = io.InquireAttribute<double>("r64");
+
+    EXPECT_EQ(attr_iString, nullptr);
+    EXPECT_EQ(attr_i8, nullptr);
+    EXPECT_EQ(attr_i16, nullptr);
+    EXPECT_EQ(attr_i32, nullptr);
+    EXPECT_EQ(attr_i64, nullptr);
+
+    EXPECT_EQ(attr_u8, nullptr);
+    EXPECT_EQ(attr_u16, nullptr);
+    EXPECT_EQ(attr_u32, nullptr);
+    EXPECT_EQ(attr_u64, nullptr);
+
+    EXPECT_EQ(attr_r32, nullptr);
+    EXPECT_EQ(attr_r64, nullptr);
+}
+
 int main(int argc, char **argv)
 {
 #ifdef ADIOS2_HAVE_MPI
diff --git a/testing/adios2/interface/TestADIOSDefineVariable.cpp b/testing/adios2/interface/TestADIOSDefineVariable.cpp
index 4910db51d7a2bba693cb628ca622111fcc008b16..db627facd4da52b4cbd30e19ed383cda939e2326 100644
--- a/testing/adios2/interface/TestADIOSDefineVariable.cpp
+++ b/testing/adios2/interface/TestADIOSDefineVariable.cpp
@@ -418,6 +418,135 @@ TEST_F(ADIOSDefineVariableTest, DefineString)
     EXPECT_NO_THROW(io.DefineVariable<std::string>("validString2", {}, {}, {}));
 }
 
+TEST_F(ADIOSDefineVariableTest, DefineAndRemove)
+{
+    auto lf_CheckRemove = [&](const std::string variableName) {
+
+        const bool isRemoved = io.RemoveVariable(variableName);
+        EXPECT_EQ(isRemoved, true);
+    };
+
+    const adios2::Dims shape = {10};
+    const adios2::Dims start = {0};
+    const adios2::Dims count = {10};
+
+    io.DefineVariable<std::string>("iString");
+    io.DefineVariable<int8_t>("i8", shape, start, count);
+    io.DefineVariable<int16_t>("i16", shape, start, count);
+    io.DefineVariable<int32_t>("i32", shape, start, count);
+    io.DefineVariable<int64_t>("i64", shape, start, count);
+    io.DefineVariable<uint8_t>("u8", shape, start, count);
+    io.DefineVariable<uint16_t>("u16", shape, start, count);
+    io.DefineVariable<uint32_t>("u32", shape, start, count);
+    io.DefineVariable<uint64_t>("u64", shape, start, count);
+    io.DefineVariable<float>("r32", shape, start, count);
+    io.DefineVariable<double>("r64", shape, start, count);
+    io.DefineVariable<std::complex<float>>("c32", shape, start, count);
+    io.DefineVariable<std::complex<double>>("c64", shape, start, count);
+
+    lf_CheckRemove("iString");
+    lf_CheckRemove("i8");
+    lf_CheckRemove("i16");
+    lf_CheckRemove("i32");
+    lf_CheckRemove("i64");
+
+    lf_CheckRemove("u8");
+    lf_CheckRemove("u16");
+    lf_CheckRemove("u32");
+    lf_CheckRemove("u64");
+
+    lf_CheckRemove("r32");
+    lf_CheckRemove("r64");
+
+    lf_CheckRemove("c32");
+    lf_CheckRemove("c64");
+
+    auto var_iString = io.InquireVariable<std::string>("iString");
+    auto var_i8 = io.InquireVariable<int8_t>("i8");
+    auto var_i16 = io.InquireVariable<int16_t>("i16");
+    auto var_i32 = io.InquireVariable<int32_t>("i32");
+    auto var_i64 = io.InquireVariable<int64_t>("i64");
+    auto var_u8 = io.InquireVariable<uint8_t>("u8");
+    auto var_u16 = io.InquireVariable<uint16_t>("u16");
+    auto var_u32 = io.InquireVariable<uint32_t>("u32");
+    auto var_u64 = io.InquireVariable<uint64_t>("u64");
+    auto var_r32 = io.InquireVariable<float>("r32");
+    auto var_r64 = io.InquireVariable<double>("r64");
+    auto var_c32 = io.InquireVariable<std::complex<float>>("c32");
+    auto var_c64 = io.InquireVariable<std::complex<double>>("c64");
+
+    EXPECT_EQ(var_iString, nullptr);
+    EXPECT_EQ(var_i8, nullptr);
+    EXPECT_EQ(var_i16, nullptr);
+    EXPECT_EQ(var_i32, nullptr);
+    EXPECT_EQ(var_i64, nullptr);
+
+    EXPECT_EQ(var_u8, nullptr);
+    EXPECT_EQ(var_u16, nullptr);
+    EXPECT_EQ(var_u32, nullptr);
+    EXPECT_EQ(var_u64, nullptr);
+
+    EXPECT_EQ(var_r32, nullptr);
+    EXPECT_EQ(var_r64, nullptr);
+
+    EXPECT_EQ(var_c32, nullptr);
+    EXPECT_EQ(var_c64, nullptr);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineAndRemoveAll)
+{
+    const adios2::Dims shape = {10};
+    const adios2::Dims start = {0};
+    const adios2::Dims count = {10};
+
+    io.DefineVariable<std::string>("iString");
+    io.DefineVariable<int8_t>("i8", shape, start, count);
+    io.DefineVariable<int16_t>("i16", shape, start, count);
+    io.DefineVariable<int32_t>("i32", shape, start, count);
+    io.DefineVariable<int64_t>("i64", shape, start, count);
+    io.DefineVariable<uint8_t>("u8", shape, start, count);
+    io.DefineVariable<uint16_t>("u16", shape, start, count);
+    io.DefineVariable<uint32_t>("u32", shape, start, count);
+    io.DefineVariable<uint64_t>("u64", shape, start, count);
+    io.DefineVariable<float>("r32", shape, start, count);
+    io.DefineVariable<double>("r64", shape, start, count);
+    io.DefineVariable<std::complex<float>>("c32", shape, start, count);
+    io.DefineVariable<std::complex<double>>("c64", shape, start, count);
+
+    io.RemoveAllVariables();
+
+    auto var_iString = io.InquireVariable<std::string>("iString");
+    auto var_i8 = io.InquireVariable<int8_t>("i8");
+    auto var_i16 = io.InquireVariable<int16_t>("i16");
+    auto var_i32 = io.InquireVariable<int32_t>("i32");
+    auto var_i64 = io.InquireVariable<int64_t>("i64");
+    auto var_u8 = io.InquireVariable<uint8_t>("u8");
+    auto var_u16 = io.InquireVariable<uint16_t>("u16");
+    auto var_u32 = io.InquireVariable<uint32_t>("u32");
+    auto var_u64 = io.InquireVariable<uint64_t>("u64");
+    auto var_r32 = io.InquireVariable<float>("r32");
+    auto var_r64 = io.InquireVariable<double>("r64");
+    auto var_c32 = io.InquireVariable<std::complex<float>>("c32");
+    auto var_c64 = io.InquireVariable<std::complex<double>>("c64");
+
+    EXPECT_EQ(var_iString, nullptr);
+    EXPECT_EQ(var_i8, nullptr);
+    EXPECT_EQ(var_i16, nullptr);
+    EXPECT_EQ(var_i32, nullptr);
+    EXPECT_EQ(var_i64, nullptr);
+
+    EXPECT_EQ(var_u8, nullptr);
+    EXPECT_EQ(var_u16, nullptr);
+    EXPECT_EQ(var_u32, nullptr);
+    EXPECT_EQ(var_u64, nullptr);
+
+    EXPECT_EQ(var_r32, nullptr);
+    EXPECT_EQ(var_r64, nullptr);
+
+    EXPECT_EQ(var_c32, nullptr);
+    EXPECT_EQ(var_c64, nullptr);
+}
+
 int main(int argc, char **argv)
 {
 #ifdef ADIOS2_HAVE_MPI