diff --git a/src/communication/export_manager.hpp b/src/communication/export_manager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccef9c1c86538a75ca38f855509c409ff647474d
--- /dev/null
+++ b/src/communication/export_manager.hpp
@@ -0,0 +1,27 @@
+//#pragma once
+//
+//#include <algorithm>
+//#include <iostream>
+//#include <fstream>
+//#include <vector>
+//#include <random>
+//
+//#include <spike.hpp>
+//
+//#include "exporter_interface.hpp"
+//
+//namespace nest {
+//namespace mc {
+//namespace communication {
+//
+//class export_manager {
+//
+//
+//
+//};
+//
+//
+//
+//} //communication
+//} // namespace mc
+//} // namespace nest
\ No newline at end of file
diff --git a/src/communication/exporter_interface.hpp b/src/communication/exporter_interface.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ecb2f7e89e014176c622578cf3534c8458e4fc9e
--- /dev/null
+++ b/src/communication/exporter_interface.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <random>
+#include <string>
+
+#include <spike.hpp>
+#include <common_types.hpp>
+
+namespace nest {
+namespace mc {
+namespace communication {
+
+template <typename Time, typename CommunicationPolicy>  // TODO: Templating on data type, for now only spike_type
+class exporter_interface {
+
+public:
+    using time_type = Time;
+    using spike_type = spike<cell_member_type, time_type>;
+
+    // Performs the export of the data, thread safe buffered
+    virtual void do_export() = 0;
+
+    // Add data to the internal storage to be exported
+    // Does not do the actual export
+    virtual void add_data(std::vector<spike_type>) = 0;
+
+    // Internal state is ok
+    // Export might encounter problems in a separate thread.
+    virtual bool ok() const = 0;
+
+    // TODO: Enum with status strings (might be added to the implemenation)
+    // returns a textual explanation of the current error state
+    // 
+    // virtual string status_description() = 0;
+    //virtual string status_id() = 0;
+};
+
+
+
+} //communication
+} // namespace mc
+} // namespace nest
\ No newline at end of file
diff --git a/src/communication/exporter_spike_file.hpp b/src/communication/exporter_spike_file.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..68b2f3c40640398002afd9296398d9dfc591fdc4
--- /dev/null
+++ b/src/communication/exporter_spike_file.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+#include <cstdio>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+#include <random>
+#include <stdexcept>
+#include <vector>
+
+#include <common_types.hpp>
+#include <util.hpp>
+#include <spike.hpp>
+
+
+#include "exporter_interface.hpp"
+
+namespace nest {
+namespace mc {
+namespace communication {
+
+template <typename Time, typename CommunicationPolicy> // TODO: Templating on data type, for now only spike_type
+class exporter_spike_file : public exporter_interface<Time, CommunicationPolicy> {
+
+public:
+    using time_type = Time;
+    using spike_type = spike<cell_member_type, time_type>;
+    using communication_policy_type = CommunicationPolicy;
+
+    // 
+    exporter_spike_file(std::string file_name, std::string path, 
+        std::string file_extention, bool over_write=true)
+        :
+        ok_(false)
+    {
+        std::string file_path(create_output_file_path(
+            file_name, path, file_extention, communication_policy_.id()));
+
+        //test if the file exist and depending on over_write throw or delete
+        std::ifstream f(file_path);
+        if (f.good()) {
+            if (!over_write) {
+                std::string error_string("Tried opening file for writing but it exists and over_write is false:\n" +
+                    file_path);
+
+                throw std::runtime_error(error_string);
+            }
+
+            std::remove(file_path.c_str());
+        }
+
+        file_handle_ = nest::mc::util::make_unique<std::ofstream>(file_path,
+                                                       std::fstream::app);
+
+        if (file_handle_->good()) {
+            ok_ = true;
+        }
+
+        // Force output of the spike times with precision
+        // TODO: We need to make this selectable
+        file_handle_->precision(4);
+        file_handle_->setf(std::ios::fixed, std::ios::floatfield);
+    }
+
+       
+    // Performs the export of the data, 
+    // Does not throw
+    void do_export() override
+    {
+        for (auto spike : spikes_) {
+            *file_handle_ << spike.source.gid << " " << spike.time << std::endl;
+        }
+        if (!file_handle_->good()){
+            ok_ = false;
+        }
+
+        spikes_.clear();
+    }
+
+    // Add data to the internal storage to be exported
+    // Does not do the actual export  
+    void add_data(std::vector<spike_type>spikes) override
+    {
+        spikes_.insert(std::end(spikes_), 
+                       std::begin(spikes), std::end(spikes));       
+    }
+
+    // Internal state is ok
+    // We are working with fstreams possibly on a seperate thread
+    // We need a way to assertain the status of the stream
+    bool ok() const override
+    {
+        return ok_ && file_handle_->good();
+    }
+
+    // Creates an indexed filename
+    static std::string create_output_file_path(std::string file_name, std::string path,
+        std::string file_extention, unsigned index)
+    {
+        std::string file_path = path + file_name + "_" + std::to_string(index) +
+                                "." + file_extention;
+        // TODO: Nest does not produce the indexing for nrank == 0
+        //       I have the feeling this disrupts consistent output. Id rather
+        //       always put the zero in.
+        return file_path;
+    }
+
+private:   
+    // Are we in a valid state?
+    bool ok_;
+
+    // Handle to our owned opened file handle
+    std::unique_ptr<std::ofstream>  file_handle_;
+    
+    // local storage for sending spikes
+    std::vector<spike_type> spikes_;
+
+    communication_policy_type communication_policy_;
+};
+
+} //communication
+} // namespace mc
+} // namespace nest
diff --git a/src/communication/exporter_spike_single_file.hpp b/src/communication/exporter_spike_single_file.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a10205fe447e18ed37ac074164cbe9bbb5d864ba
--- /dev/null
+++ b/src/communication/exporter_spike_single_file.hpp
@@ -0,0 +1,140 @@
+#pragma once
+
+#include <cstdio>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+#include <random>
+#include <stdexcept>
+#include <vector>
+
+#include <common_types.hpp>
+#include <util.hpp>
+#include <spike.hpp>
+
+
+#include "exporter_interface.hpp"
+
+namespace nest {
+namespace mc {
+namespace communication {
+
+template <typename Time, typename CommunicationPolicy> // TODO: Templating on data type, for now only spike_type
+class exporter_spike_single_file : public exporter_interface<Time, CommunicationPolicy> {
+
+public:
+    using time_type = Time;
+    using spike_type = spike<cell_member_type, time_type>;
+    using communication_policy_type = CommunicationPolicy;
+
+    // 
+    exporter_spike_single_file(std::string file_name, std::string path,
+        std::string file_extention, bool over_write=true)
+        :
+        ok_(false)
+    {
+        if (!communication_policy_.id() == 0) {
+            ok_ = true;
+            return;
+        }
+
+        std::string file_path(create_output_file_path(
+            file_name, path, file_extention, communication_policy_.id()));
+
+        //test if the file exist and depending on over_write throw or delete
+        std::ifstream f(file_path);
+        if (f.good()) {
+            if (!over_write) {
+                std::string error_string("Tried opening file for writing but it exists and over_write is false:\n" +
+                    file_path);
+
+                throw std::runtime_error(error_string);
+            }
+
+            std::remove(file_path.c_str());
+        }
+
+        file_handle_ = nest::mc::util::make_unique<std::ofstream>(file_path,
+                                                       std::fstream::app);
+
+        if (file_handle_->good()) {
+            ok_ = true;
+        }
+
+        // Force output of the spike times with precision
+        // TODO: We need to make this selectable
+        file_handle_->precision(4);
+        file_handle_->setf(std::ios::fixed, std::ios::floatfield);
+    }
+
+       
+    // Performs the export of the data, 
+    // Does not throw
+    void do_export() override
+    {        
+        if (!communication_policy_.id() == 0) {
+            return;
+        }
+
+        for (auto spike : spikes_) {
+            *file_handle_ << spike.source.gid << " " << spike.time << std::endl;
+        }
+        if (!file_handle_->good()){
+            ok_ = false;
+        }
+
+        spikes_.clear();
+    }
+
+    // Add data to the internal storage to be exported
+    // Does not do the actual export  
+    void add_data(std::vector<spike_type>spikes) override
+    {
+        if (!communication_policy_.id() == 0) {
+            return;
+        }
+
+        spikes_.insert(std::end(spikes_), 
+                       std::begin(spikes), std::end(spikes));       
+    }
+
+    // Internal state is ok
+    // We are working with fstreams possibly on a seperate thread
+    // We need a way to assertain the status of the stream
+    bool ok() const override
+    {
+        if (!communication_policy_.id() == 0) {
+            return true;
+        }
+
+        return ok_ && file_handle_->good();
+    }
+
+    // Creates an indexed filename
+    static std::string create_output_file_path(std::string file_name, std::string path,
+        std::string file_extention, unsigned index)
+    {
+        std::string file_path = path + file_name + "_" + std::to_string(index) +
+                                "." + file_extention;
+        // TODO: Nest does not produce the indexing for nrank == 0
+        //       I have the feeling this disrupts consistent output. Id rather
+        //       always put the zero in.
+        return file_path;
+    }
+
+private:   
+    // Are we in a valid state?
+    bool ok_;
+
+    // Handle to our owned opened file handle
+    std::unique_ptr<std::ofstream>  file_handle_;
+    
+    // local storage for sending spikes
+    std::vector<spike_type> spikes_;
+
+    communication_policy_type communication_policy_;
+};
+
+} //communication
+} // namespace mc
+} // namespace nest
diff --git a/src/model.hpp b/src/model.hpp
index 84dd84298a78418ce882b68a29f2211a6e50401b..b92ca4a89a2e28ea8ced46def014dc9b2b8cd07c 100644
--- a/src/model.hpp
+++ b/src/model.hpp
@@ -7,10 +7,12 @@
 #include <cell.hpp>
 #include <cell_group.hpp>
 #include <fvm_cell.hpp>
+#include <memory>
 #include <recipe.hpp>
 #include <thread_private_spike_store.hpp>
 #include <communication/communicator.hpp>
 #include <communication/global_policy.hpp>
+#include <communication/exporter_interface.hpp>
 #include <profiling/profiler.hpp>
 
 #include "trace_sampler.hpp"
@@ -182,6 +184,8 @@ private:
     using local_spike_store_type = thread_private_spike_store<time_type>;
     util::double_buffer< local_spike_store_type > local_spikes_;
 
+    using exporter_interface_type = nest::mc::communication::exporter_interface<time_type, communicator_type>;
+    std::unique_ptr<exporter_interface_type> exporter_;
     // Convenience functions that map the spike buffers and event queues onto
     // the appropriate integration interval.
     //
diff --git a/tests/global_communication/CMakeLists.txt b/tests/global_communication/CMakeLists.txt
index f7d000157e4cfd130399d1f718b67fbc5eb2f86d..dff31ad71c6ac5c30a840073fb012405f652a584 100644
--- a/tests/global_communication/CMakeLists.txt
+++ b/tests/global_communication/CMakeLists.txt
@@ -1 +1,32 @@
-# Nothing to be done yet
+set(HEADERS
+    ${PROJECT_SOURCE_DIR}/src/swcio.hpp
+)
+set(COMMUNICATION_SOURCES
+    test_exporter_spike_file.cpp
+    test_exporter_spike_single_file.cpp
+    # unit test driver
+    test.cpp
+)
+
+add_executable(global_communication.exe ${COMMUNICATION_SOURCES} ${HEADERS})
+
+set(TARGETS global_communication.exe)
+
+foreach(target ${TARGETS})
+    target_link_libraries(${target} LINK_PUBLIC cellalgo gtest)
+    
+    if(WITH_TBB)
+    target_link_libraries(${target} LINK_PUBLIC ${TBB_LIBRARIES})
+    endif()
+
+    if(WITH_MPI)
+    target_link_libraries(${target} LINK_PUBLIC ${MPI_C_LIBRARIES})
+    set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS "${MPI_C_LINK_FLAGS}")
+    endif()
+
+    set_target_properties(${target}
+       PROPERTIES
+       RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests"
+    )
+endforeach()
+
diff --git a/tests/global_communication/test.cpp b/tests/global_communication/test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c67a065bd88ed85aa56e865b1d4f8f9fa3d5677e
--- /dev/null
+++ b/tests/global_communication/test.cpp
@@ -0,0 +1,19 @@
+#include <iostream>
+#include <fstream>
+#include <numeric>
+#include <vector>
+
+#include "gtest.h"
+
+#include "../../src/communication/communicator.hpp"
+#include "../../src/communication/global_policy.hpp"
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // We need to set the communicator policy at the top level
+    // this allows us to build multiple communicators in the tests
+    nest::mc::communication::global_policy_guard global_guard(argc, argv);
+
+    return RUN_ALL_TESTS();
+}
diff --git a/tests/global_communication/test_exporter_spike_file.cpp b/tests/global_communication/test_exporter_spike_file.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d30877cde4bd62bf8c5737d1ba365cd1c14b67e
--- /dev/null
+++ b/tests/global_communication/test_exporter_spike_file.cpp
@@ -0,0 +1,118 @@
+#include "gtest.h"
+
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <communication/communicator.hpp>
+#include <communication/global_policy.hpp>
+#include <communication/exporter_spike_file.hpp>
+
+class exporter_spike_file_fixture : public ::testing::Test {
+
+protected:
+    using time_type = float;
+    using communicator_type = nest::mc::communication::global_policy;
+
+    using spike_type = nest::mc::communication::exporter_spike_file<time_type, 
+        communicator_type>::spike_type;
+
+    using exporter_type = nest::mc::communication::exporter_spike_file<time_type, communicator_type>;
+    std::string file_name;
+    std::string path;
+    std::string extention;
+    unsigned index;
+
+    exporter_spike_file_fixture()
+        :
+        file_name("spikes"),
+        path("./"),
+        extention("gdf"),
+        index(0)
+    {}
+
+    std::string get_standard_file_name()
+    {
+        return exporter_type::create_output_file_path(
+            file_name, path, extention, index);
+    }
+
+    void SetUp() {
+        // code here will execute just before the test ensues 
+    }
+
+    void TearDown() {
+        // delete the start create file
+        std::remove(get_standard_file_name().c_str());
+    }
+
+    ~exporter_spike_file_fixture() {
+
+    }
+};
+
+TEST_F(exporter_spike_file_fixture, constructor)
+{
+    exporter_type exporter(file_name,
+        path, extention, index);
+
+    // after construction the state of the exporter should be valid
+    EXPECT_TRUE(exporter.ok());
+
+
+    //test if the file exist and depending on over_write throw or delete
+    std::ifstream f(get_standard_file_name());
+    EXPECT_TRUE(f.good());
+}
+
+TEST_F(exporter_spike_file_fixture, create_output_file_path)
+{
+    // Create some random paths, no need for fancy tests here
+    std::string produced_filename =
+        exporter_type::create_output_file_path(
+            "spikes", "./", "gdf", 0);
+    EXPECT_STREQ(produced_filename.c_str(), "./spikes_0.gdf");
+
+    produced_filename =
+        exporter_type::create_output_file_path(
+            "a_name", "../../", "txt", 5);
+    EXPECT_STREQ(produced_filename.c_str(), "../../a_name_5.txt");
+}
+
+TEST_F(exporter_spike_file_fixture, do_export)
+{
+    
+
+    exporter_type exporter(file_name,
+        path, extention, index);
+
+    // Create some spikes
+    std::vector<spike_type> spikes;
+    spikes.push_back({ { 0, 0 }, 0.0});
+    spikes.push_back({ { 0, 0 }, 0.1 });
+    spikes.push_back({ { 1, 0 }, 1.0 });
+    spikes.push_back({ { 1, 0 }, 1.1 });
+
+    // add to the exporter
+    exporter.add_data(spikes);
+
+    // now do the export
+    exporter.do_export();
+
+    // Test if we have spikes in the file
+    std::ifstream f(get_standard_file_name());
+    EXPECT_TRUE(f.good());
+
+    std::string line;
+
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "0 0.0000");
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "0 0.1000");
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "1 1.0000");
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "1 1.1000");
+}
diff --git a/tests/global_communication/test_exporter_spike_single_file.cpp b/tests/global_communication/test_exporter_spike_single_file.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aee5bb9ce685455bc8fdc3531f6b6c27abe68684
--- /dev/null
+++ b/tests/global_communication/test_exporter_spike_single_file.cpp
@@ -0,0 +1,118 @@
+#include "gtest.h"
+
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <communication/communicator.hpp>
+#include <communication/global_policy.hpp>
+#include <communication/exporter_spike_single_file.hpp>
+
+class exporter_spike_single_file_fixture : public ::testing::Test {
+
+protected:
+    using time_type = float;
+    using communicator_type = nest::mc::communication::global_policy;
+
+    using spike_type = nest::mc::communication::exporter_spike_single_file<time_type,
+        communicator_type>::spike_type;
+
+    using exporter_type = nest::mc::communication::exporter_spike_single_file<time_type, communicator_type>;
+    std::string file_name;
+    std::string path;
+    std::string extention;
+    unsigned index;
+
+    exporter_spike_single_file_fixture()
+        :
+        file_name("spikes"),
+        path("./"),
+        extention("gdf"),
+        index(0)
+    {}
+
+    std::string get_standard_file_name()
+    {
+        return exporter_type::create_output_file_path(
+            file_name, path, extention, index);
+    }
+
+    void SetUp() {
+        // code here will execute just before the test ensues 
+    }
+
+    void TearDown() {
+        // delete the start create file
+        std::remove(get_standard_file_name().c_str());
+    }
+
+    ~exporter_spike_single_file_fixture() {
+
+    }
+};
+
+TEST_F(exporter_spike_single_file_fixture, constructor)
+{
+    exporter_type exporter(file_name,
+        path, extention, index);
+
+    // after construction the state of the exporter should be valid
+    EXPECT_TRUE(exporter.ok());
+
+
+    //test if the file exist and depending on over_write throw or delete
+    std::ifstream f(get_standard_file_name());
+    EXPECT_TRUE(f.good());
+}
+
+TEST_F(exporter_spike_single_file_fixture, create_output_file_path)
+{
+    // Create some random paths, no need for fancy tests here
+    std::string produced_filename =
+        exporter_type::create_output_file_path(
+            "spikes", "./", "gdf", 0);
+    EXPECT_STREQ(produced_filename.c_str(), "./spikes_0.gdf");
+
+    produced_filename =
+        exporter_type::create_output_file_path(
+            "a_name", "../../", "txt", 5);
+    EXPECT_STREQ(produced_filename.c_str(), "../../a_name_5.txt");
+}
+
+TEST_F(exporter_spike_single_file_fixture, do_export)
+{
+    
+
+    exporter_type exporter(file_name,
+        path, extention, index);
+
+    // Create some spikes
+    std::vector<spike_type> spikes;
+    spikes.push_back({ { 0, 0 }, 0.0});
+    spikes.push_back({ { 0, 0 }, 0.1 });
+    spikes.push_back({ { 1, 0 }, 1.0 });
+    spikes.push_back({ { 1, 0 }, 1.1 });
+
+    // add to the exporter
+    exporter.add_data(spikes);
+
+    // now do the export
+    exporter.do_export();
+
+    // Test if we have spikes in the file
+    std::ifstream f(get_standard_file_name());
+    EXPECT_TRUE(f.good());
+
+    std::string line;
+
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "0 0.0000");
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "0 0.1000");
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "1 1.0000");
+    EXPECT_TRUE(std::getline(f, line));
+    EXPECT_STREQ(line.c_str(), "1 1.1000");
+}