diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp
index f0c608309c67d258fecce2f84e44c061bb2a474a..be9bcd1dc5b2bca9a657aeeb21d2514affdd5f05 100644
--- a/miniapp/miniapp.cpp
+++ b/miniapp/miniapp.cpp
@@ -3,6 +3,7 @@
 #include <iostream>
 #include <fstream>
 #include <memory>
+#include <vector>
 
 #include <json/src/json.hpp>
 
@@ -16,6 +17,7 @@
 #include <profiling/profiler.hpp>
 #include <communication/communicator.hpp>
 #include <communication/global_policy.hpp>
+#include <communication/exporter_spike_file.hpp>
 #include <util/ioutil.hpp>
 #include <util/optional.hpp>
 
@@ -29,12 +31,15 @@ using global_policy = communication::global_policy;
 
 using lowered_cell = fvm::fvm_cell<double, cell_local_size_type>;
 using model_type = model<lowered_cell>;
-using sample_trace_type = sample_trace<model_type::time_type, model_type::value_type>;
-
+using time_type = model_type::time_type;
+using sample_trace_type = sample_trace<time_type, model_type::value_type>;
+using file_export_type = communication::exporter_spike_file<time_type, global_policy>;
 void banner();
 std::unique_ptr<recipe> make_recipe(const io::cl_options&, const probe_distribution&);
 std::unique_ptr<sample_trace_type> make_trace(cell_member_type probe_id, probe_spec probe);
 std::pair<cell_gid_type, cell_gid_type> distribute_cells(cell_size_type ncells);
+using communicator_type = communication::communicator<time_type, communication::global_policy>;
+using spike_type = typename communicator_type::spike_type;
 
 void write_trace_json(const sample_trace_type& trace, const std::string& prefix = "trace_");
 
@@ -63,15 +68,35 @@ int main(int argc, char** argv) {
 
         // build model from recipe
         // TODO: I would rather just forward the options object. 
-        model_type::file_output_parameters model_params(
-            options.spike_file_output,
-            options.single_file_per_rank,
-            options.over_write,
-            options.output_path,
-            options.file_name,
-            options.file_extention
-        );
-        model_type m(*recipe, cell_range.first, cell_range.second, model_params);
+
+        model_type m(*recipe, cell_range.first, cell_range.second);
+        std::unique_ptr<file_export_type> file_exporter;
+        if (!options.spike_file_output) {
+            m.set_global_spike_callback(
+                file_export_type::do_nothing);
+            m.set_local_spike_callback(
+                file_export_type::do_nothing);
+        }
+        else {
+            file_exporter = nest::mc::util::make_unique<file_export_type>(
+                options.file_name, options.output_path, 
+                options.file_extention, true);
+
+            if (options.single_file_per_rank) {
+                    m.set_global_spike_callback(
+                        file_export_type::do_nothing);
+                    m.set_local_spike_callback(
+                        [&](const std::vector<spike_type>& spikes) { file_exporter->do_export(spikes); });
+
+             }
+             else {
+                 m.set_global_spike_callback(
+                     [&](const std::vector<spike_type>& spikes) { file_exporter->do_export(spikes); });
+                   m.set_local_spike_callback(
+                       file_export_type::do_nothing);
+             }
+        }
+       
 
         // inject some artificial spikes, 1 per 20 neurons.
         cell_gid_type spike_cell = 20*((cell_range.first+19)/20);
diff --git a/src/communication/export_manager.hpp b/src/communication/export_manager.hpp
deleted file mode 100644
index 99354ab6bff8004b3cc6c2a85a3e5fa57571d8a1..0000000000000000000000000000000000000000
--- a/src/communication/export_manager.hpp
+++ /dev/null
@@ -1,144 +0,0 @@
-#pragma once
-
-#include <algorithm>
-#include <iostream>
-
-#include <vector>
-#include <memory>
-#include <utility>
-#include <string>
-
-#include <spike.hpp>
-#include <util.hpp>
-#include <common_types.hpp>
-#include "exporter_interface.hpp"
-#include "exporter_spike_file.hpp"
-#include "exporter_spike_single_file.hpp"
-
-namespace nest {
-namespace mc {
-namespace communication {
-
-
-// export_manager manages the export of simulation parameters to the outside 
-// world. Examples could be output to disk, but also more advanced communication
-// via mpi can be possible.
-// The parameters to be exported are buffered locally.
-// There are two export methods implemented: rank local where an export is
-// done on each rank and a single export per simulation
-// The output file is constructed from constructor arguments and will always
-// contain a index also when a single file is written. THis allows automated
-// parsing with a simple regex
-// 
-// TODO: The exporter currently only exports spikes to file. The constructor
-// arguments reflect this. In future version a better way to configure this
-// class is needed.
-template <typename Time, typename CommunicationPolicy>
-class export_manager {
-public:
-    using time_type = Time;
-    using spike_type = spike<cell_member_type, time_type>;
-
-    // Constructor
-    // spike_file_output initiates spike file output. If false the object is 
-    //          constructed in a valid state. No exporters are registed so no output
-    //          is done
-    // single_file_per_rank if true only rank zero performs output to disk
-    // over_write if true will overwrite the specified output file
-    // output_path  relative or absolute path
-    // file_name    will be appended with "_x" with x the rank number
-    // file_extention  a seperator will be added automatically
-    export_manager(bool spike_file_output, bool single_file_per_rank, bool over_write,
-        std::string output_path, std::string file_name, std::string file_extention)
-        :
-        spike_file_output_(spike_file_output) 
-    {
-        // simple switch to turn of the export, object will still be in a valid
-        // state.
-        if (!spike_file_output_) {
-            return;
-        }
-
-        // single file per rank exporters
-        if (single_file_per_rank) { 
-            rank_exporters_.push_back(
-                nest::mc::util::make_unique<
-                    nest::mc::communication::exporter_spike_file<Time, CommunicationPolicy> >(
-                        file_name, output_path, file_extention, over_write));
-        }
-
-        // single file per simulation exporters
-        if (!single_file_per_rank) {  // TODO: When we add more exporters and 
-            //agreed on the parameter input this should be cleanup up.
-            if (communication_policy_.id() == 0) {
-                single_exporters_.push_back(
-                    nest::mc::util::make_unique<
-                        nest::mc::communication::exporter_spike_file<Time, CommunicationPolicy> >(
-                            file_name, output_path, file_extention, over_write));
-
-            }
-        }
-    }
-
-    // Perform a export of local spikes, typically used for exporting to multi-
-    // ple files from each rank individually.
-    // spikes are buffer before export
-    void local_export_callback(const std::vector<spike_type>& spikes)
-    {
-        // TODO: No export needed, so exit
-        if (!spike_file_output_) {
-            return;
-        }
-
-        local_spikes_.insert(std::end(local_spikes_),
-            std::begin(spikes), std::end(spikes));
-
-        // TODO: Do each exporter in a parallel thread?
-        for (auto &exporter : rank_exporters_) {
-            exporter->do_export(spikes);
-        }
-
-        local_spikes_.clear();
-    }
-
-    // Perform a export of global spikes, typically used for exporting spikes
-    // from a single rank in a simulation
-    // spikes are buffer before export
-    void global_export_callback(const std::vector<spike_type>& spikes)
-    {
-        if (!spike_file_output_) {
-            return;
-        }
-
-        // We only output on a single rank
-        if (!communication_policy_.id() == 0) {
-            return;
-        }
-
-        global_spikes_.insert(std::end(global_spikes_),
-            std::begin(spikes), std::end(spikes));
-
-        // TODO: Do each exporter in a parallel thread?
-        for (auto &exporter : single_exporters_) {
-            exporter->do_export(spikes);
-        }
-
-        global_spikes_.clear();
-    }
-
-private:
-    bool spike_file_output_;
-    
-    std::vector<std::unique_ptr<exporter_interface<Time, CommunicationPolicy> > > rank_exporters_;
-    std::vector<std::unique_ptr<exporter_interface<Time, CommunicationPolicy> > > single_exporters_;
-
-    CommunicationPolicy communication_policy_;
-
-    // local buffer for spikes
-    std::vector<spike_type> local_spikes_;
-    std::vector<spike_type> global_spikes_;
-};
-
-} //communication
-} // namespace mc
-} // namespace nest
diff --git a/src/communication/exporter_interface.hpp b/src/communication/exporter_interface.hpp
index d0370a92b609773b06cb8663563129a242385cb1..8f7a714c9a1a735d338950c130debab89c0e3123 100644
--- a/src/communication/exporter_interface.hpp
+++ b/src/communication/exporter_interface.hpp
@@ -26,6 +26,10 @@ public:
 
     // Returns the status of the exporter
     virtual bool good() const = 0;
+
+    // Static NULL version of the do_export function for NOP callbacks
+    static void do_nothing(const std::vector<spike_type>&)
+    {}
 };
 
 } //communication
diff --git a/src/model.hpp b/src/model.hpp
index 14a5f9d82a70b502f4e4c14553a45b28e0701160..f6d3f7922ae925a7bb6831d7f7b028277318b5ba 100644
--- a/src/model.hpp
+++ b/src/model.hpp
@@ -12,7 +12,6 @@
 #include <thread_private_spike_store.hpp>
 #include <communication/communicator.hpp>
 #include <communication/global_policy.hpp>
-#include <communication/export_manager.hpp>
 #include <profiling/profiler.hpp>
 
 #include "trace_sampler.hpp"
@@ -23,47 +22,19 @@ namespace mc {
 template <typename Cell>
 class model {
 public:
-
-    // TODO:We need to think how to transport parameters accros the different classes
-    // Move the io to src directory would make it allot easier!!
-    struct file_output_parameters
-    {
-        bool spike_file_output;
-        bool single_file_per_rank;
-        bool over_write;
-        std::string output_path;
-        std::string file_name;
-        std::string file_extention;
-
-        file_output_parameters(bool spike_file_output_i,
-            bool single_file_per_rank_i,
-            bool over_write_i,
-            std::string output_path_i,
-            std::string file_name_i,
-            std::string file_extention_i)
-            :
-            spike_file_output(spike_file_output_i),
-            single_file_per_rank(single_file_per_rank_i),
-            over_write(over_write_i),
-            output_path(output_path_i),
-            file_name(file_name_i),
-            file_extention(file_extention_i)
-        {}
-    };
-
     using cell_group_type = cell_group<Cell>;
-    using time_type = typename cell_group_type::time_type;
+    using time_type = typename cell_group_type::time_type;   
     using value_type = typename cell_group_type::value_type;
     using communicator_type = communication::communicator<time_type, communication::global_policy>;
     using sampler_function = typename cell_group_type::sampler_function;
+    using spike_type = typename communicator_type::spike_type;
 
     struct probe_record {
         cell_member_type id;
         probe_spec probe;
     };
 
-    model(const recipe& rec, cell_gid_type cell_from, cell_gid_type cell_to,
-        file_output_parameters file_output_parameters_i):
+    model(const recipe& rec, cell_gid_type cell_from, cell_gid_type cell_to):
         cell_from_(cell_from),
         cell_to_(cell_to),
         communicator_(cell_from, cell_to)
@@ -99,14 +70,6 @@ public:
         }
         communicator_.construct();
 
-        exporter_ = nest::mc::util::make_unique<exporter_manager_type>(
-            file_output_parameters_i.spike_file_output,
-            file_output_parameters_i.single_file_per_rank,
-            file_output_parameters_i.over_write,
-            file_output_parameters_i.output_path,
-            file_output_parameters_i.file_name,
-            file_output_parameters_i.file_extention);
-
         // Allocate an empty queue buffer for each cell group
         // These must be set initially to ensure that a queue is available for each
         // cell group for the first time step.
@@ -144,7 +107,7 @@ public:
             auto update_cells = [&] () {
                 threading::parallel_for::apply(
                     0u, cell_groups_.size(),
-                    [&](unsigned i) {
+                     [&](unsigned i) {
                         auto &group = cell_groups_[i];
 
                         PE("stepping","events");
@@ -173,10 +136,10 @@ public:
             auto exchange = [&] () {
                 PE("stepping", "exchange");
                 auto local_spikes = previous_spikes().gather();
-                exporter_->local_export_callback(local_spikes);
+                local_export_callback_(local_spikes);
                 future_events() = communicator_.exchange(local_spikes,
-                    // send the exporter function as pointers to export
-                    [&] (const std::vector<spike_type>& spikes){ exporter_->global_export_callback(spikes); });
+                    // send the exporter function as pointer
+                    [&] (const std::vector<spike_type>& spikes){ global_export_callback_(spikes); });
                 PL(2);
             };
 
@@ -215,6 +178,19 @@ public:
     std::size_t num_spikes() const { return communicator_.num_spikes(); }
     std::size_t num_groups() const { return cell_groups_.size(); }
 
+    void set_global_spike_callback(std::function<void(
+        const std::vector<spike_type>&)> global_export_callback)
+    {
+        global_export_callback_ = global_export_callback;
+    }
+    void set_local_spike_callback(std::function<void(
+        const std::vector<spike_type>&)> local_export_callback)
+    {
+        local_export_callback_ = local_export_callback;
+    }
+
+
+
 private:
     cell_gid_type cell_from_;
     cell_gid_type cell_to_;
@@ -222,7 +198,7 @@ private:
     std::vector<cell_group_type> cell_groups_;
     communicator_type communicator_;
     std::vector<probe_record> probes_;
-    using spike_type = typename communicator_type::spike_type;
+    
 
     using event_queue_type = typename communicator_type::event_queue;
     util::double_buffer< std::vector<event_queue_type> > event_queues_;
@@ -230,8 +206,8 @@ private:
     using local_spike_store_type = thread_private_spike_store<time_type>;
     util::double_buffer< local_spike_store_type > local_spikes_;
 
-    using exporter_manager_type = nest::mc::communication::export_manager<time_type, communication::global_policy>;
-    std::unique_ptr<exporter_manager_type> exporter_;
+    std::function<void(const std::vector<spike_type>&)> global_export_callback_;
+    std::function<void(const std::vector<spike_type>&)> local_export_callback_;
     // Convenience functions that map the spike buffers and event queues onto
     // the appropriate integration interval.
     //
diff --git a/tests/performance/io/disk_io.cpp b/tests/performance/io/disk_io.cpp
index 877896759cc5637c52f5a3a18a567f6e2e2e5606..fa9973939d49db62b6427d80f2f9198c69dee26c 100644
--- a/tests/performance/io/disk_io.cpp
+++ b/tests/performance/io/disk_io.cpp
@@ -13,7 +13,7 @@
 
 #include <communication/communicator.hpp>
 #include <communication/global_policy.hpp>
-#include <communication/export_manager.hpp>
+#include <communication/exporter_spike_file.hpp>
 #include <profiling/profiler.hpp>
 
 using namespace nest::mc;
@@ -74,8 +74,8 @@ int main(int argc, char** argv)
     }
 
     // Create the sut  
-   communication::export_manager<time_type, global_policy> manager(
-        true, file_per_rank, true, "./", "spikes", "gdf");
+   communication::exporter_spike_file<time_type, global_policy> exporter(
+         "spikes", "./", "gdf", true);
 
     // We need the nr of ranks to calculate the nr of spikes to produce per
     // rank
@@ -106,7 +106,7 @@ int main(int argc, char** argv)
     for (auto idx = 0; idx < nr_repeats; ++idx) {
         auto time_start = timer::tic();
 
-        manager.local_export_callback(spikes);
+        exporter.do_export(spikes);
         auto run_time = timer::toc(time_start);
         time_total += run_time;
         timings_arr[idx] = run_time;