diff --git a/src/fileutils.cpp b/src/fileutils.cpp
index f2c3869b8b2ea203b517fcadbe68454186a47f2e..a5e25066d066b17e737a6d36a40760fe27d26120 100644
--- a/src/fileutils.cpp
+++ b/src/fileutils.cpp
@@ -42,7 +42,9 @@
 #if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
 #include "client/ring_signal.h"
 #endif
+
 #ifdef _WIN32
+#include <windows.h>
 #include "string_utils.h"
 #endif
 
@@ -227,9 +229,27 @@ getFileLock(const std::string& path)
     return fileLocks[path];
 }
 
-bool isFile (const std::string& path) {
-  struct stat s;
-  return (stat (path.c_str(), &s) == 0) and not (s.st_mode & S_IFDIR);
+bool isFile(const std::string& path, bool resolveSymlink)
+{
+    if (resolveSymlink) {
+        struct stat s;
+        if (stat(path.c_str(), &s) == 0)
+            return S_ISREG(s.st_mode);
+    } else {
+#ifdef _WIN32
+        DWORD attr = GetFileAttributesA(path.c_str());
+        if ((attr != INVALID_FILE_ATTRIBUTES) &&
+            !(attr & FILE_ATTRIBUTE_DIRECTORY) &&
+            !(attr & FILE_ATTRIBUTE_REPARSE_POINT))
+            return true;
+#else
+        struct stat s;
+        if (lstat(path.c_str(), &s) == 0)
+            return S_ISREG(s.st_mode);
+#endif
+    }
+
+    return false;
 }
 
 bool isDirectory(const std::string& path)
@@ -705,8 +725,140 @@ recursive_mkdir(const std::string& path, mode_t mode)
     return true;
 }
 
+#ifdef _WIN32
+bool
+eraseFile_win32(const std::string& path, bool dosync)
+{
+    HANDLE h = CreateFileA(path.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+    if (h == INVALID_HANDLE_VALUE) {
+        JAMI_WARN("Can not open file %s for erasing.", path.c_str());
+        return false;
+    }
+
+    LARGE_INTEGER size;
+    if (!GetFileSizeEx(h, &size)) {
+        JAMI_WARN("Can not erase file %s: GetFileSizeEx() failed.", path.c_str());
+        CloseHandle(h);
+        return false;
+    }
+    if (size.QuadPart == 0) {
+        CloseHandle(h);
+        return false;
+    }
+
+    uint64_t size_blocks = size.QuadPart / ERASE_BLOCK;
+    if (size.QuadPart % ERASE_BLOCK)
+        size_blocks++;
+
+    char* buffer;
+    try {
+        buffer = new char[ERASE_BLOCK];
+    }
+    catch (std::bad_alloc& ba) {
+        JAMI_WARN("Can not allocate buffer for erasing %s.", path.c_str());
+        CloseHandle(h);
+        return false;
+    }
+    memset(buffer, 0x00, ERASE_BLOCK);
+
+    OVERLAPPED ovlp;
+    if (size.QuadPart < (1024-42)) { // a small file can be stored in the MFT record
+        ovlp.Offset = 0;
+        ovlp.OffsetHigh = 0;
+        WriteFile(h, buffer, (DWORD)size.QuadPart, 0, &ovlp);
+        FlushFileBuffers(h);
+    }
+    for (uint64_t i = 0; i < size_blocks; i++) {
+        uint64_t offset = i * ERASE_BLOCK;
+        ovlp.Offset = offset & 0x00000000FFFFFFFF;
+        ovlp.OffsetHigh = offset >> 32;
+        WriteFile(h, buffer, ERASE_BLOCK, 0, &ovlp);
+    }
+
+    delete[] buffer;
+
+    if (dosync)
+        FlushFileBuffers(h);
+
+    CloseHandle(h);
+    return true;
+}
+
+#else
+
+bool
+eraseFile_posix(const std::string& path, bool dosync)
+{
+    int fd = open(path.c_str(), O_WRONLY);
+    if (fd == -1) {
+        JAMI_WARN("Can not open file %s for erasing.", path.c_str());
+        return false;
+    }
+
+    struct stat st;
+    if (fstat(fd, &st) == -1) {
+        JAMI_WARN("Can not erase file %s: fstat() failed.", path.c_str());
+        close(fd);
+        return false;
+    }
+
+    if (st.st_size == 0) {
+        close(fd);
+        return false;
+    }
+
+    uintmax_t size_blocks = st.st_size / ERASE_BLOCK;
+    if (st.st_size % ERASE_BLOCK)
+        size_blocks++;
+
+    char* buffer;
+    try {
+        buffer = new char[ERASE_BLOCK];
+    }
+    catch (std::bad_alloc& ba) {
+        JAMI_WARN("Can not allocate buffer for erasing %s.", path.c_str());
+        close(fd);
+        return false;
+    }
+    memset(buffer, 0x00, ERASE_BLOCK);
+
+    for (uintmax_t i = 0; i < size_blocks; i++) {
+        lseek(fd, i * ERASE_BLOCK, SEEK_SET);
+        write(fd, buffer, ERASE_BLOCK);
+    }
+
+    delete[] buffer;
+
+    if (dosync)
+        fsync(fd);
+
+    close(fd);
+    return true;
+}
+#endif
+
+bool
+eraseFile(const std::string& path, bool dosync)
+{
+#ifdef _WIN32
+    return eraseFile_win32(path, dosync);
+#else
+    return eraseFile_posix(path, dosync);
+#endif
+}
+
+int
+remove(const std::string& path, bool erase)
+{
+    if (erase and isFile(path, false)) {
+        eraseFile(path, true);
+    }
+
+    return std::remove(path.c_str());
+}
+
 int
-removeAll(const std::string& path)
+removeAll(const std::string& path, bool erase)
 {
     if (path.empty())
         return -1;
@@ -715,9 +867,9 @@ removeAll(const std::string& path)
         if (dir.back() != DIR_SEPARATOR_CH)
             dir += DIR_SEPARATOR_CH;
         for (auto& entry : fileutils::readDirectory(dir))
-            removeAll(dir + entry);
+            removeAll(dir + entry, erase);
     }
-    return remove(path);
+    return remove(path, erase);
 }
 
 }} // namespace jami::fileutils
diff --git a/src/fileutils.h b/src/fileutils.h
index c1faccd301eb9740c443a67e0c54e274eb0e39c8..06a561f0b16e817ec0cf99ce8c883239965d0ca5 100644
--- a/src/fileutils.h
+++ b/src/fileutils.h
@@ -41,7 +41,7 @@
 #define XDG_CACHE_HOME          (PROTECTED_GETENV("XDG_CACHE_HOME"))
 
 #define PIDFILE ".ring.pid"
-
+#define ERASE_BLOCK 4096
 
 #ifndef _WIN32
 #include <sys/stat.h>           // mode_t
@@ -89,9 +89,8 @@ namespace jami { namespace fileutils {
      */
     std::string getFullPath(const std::string& base, const std::string& path);
 
-    bool isFile(const std::string& path);
+    bool isFile(const std::string& path, bool resolveSymlink = true);
     bool isDirectory(const std::string& path);
-
     bool isSymLink(const std::string& path);
 
     std::chrono::system_clock::time_point writeTime(const std::string& path);
@@ -124,15 +123,16 @@ namespace jami { namespace fileutils {
     FileHandle create_pidfile();
 
     /**
-     * Direct binding on std::remove, with std::string as argument
+     * Remove a file with optional erasing of content.
+     * Return the same value as std::remove().
      */
-    static inline int remove(const std::string& path) { return std::remove(path.c_str()); }
+    int remove(const std::string& path, bool erase = false);
 
     /**
      * Prune given directory's content and remove it, symlinks are not followed.
      * Return 0 if succeed, -1 if directory is not removed (content can be removed partially).
      */
-    int removeAll(const std::string& path);
+    int removeAll(const std::string& path, bool erase = false);
 
 }} // namespace jami::fileutils
 
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 32111bb1639e094541fd1873bb6df0e25cf5bda4..d087d8a075ce5dbbb56c2c4e16f7a61e261a96a7 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -335,7 +335,7 @@ JamiAccount::flush()
 
     fileutils::removeAll(dataPath_);
     fileutils::removeAll(cachePath_);
-    fileutils::removeAll(idPath_);
+    fileutils::removeAll(idPath_, true);
 }
 
 std::shared_ptr<SIPCall>