diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp
index 960c3ccb4f52d7b27ac186ae9cb3f5f018c8ee7b..3582df425e74e1cd123c8837143fff57105af91e 100644
--- a/miniapp/miniapp.cpp
+++ b/miniapp/miniapp.cpp
@@ -35,7 +35,7 @@ using lowered_cell = fvm::fvm_multicell<gpu::backend>;
 using lowered_cell = fvm::fvm_multicell<multicore::backend>;
 #endif
 using model_type = model<lowered_cell>;
-using sample_trace_type = sample_trace<model_type::time_type, double>;
+using sample_trace_type = sample_trace<time_type, double>;
 using file_export_type = io::exporter_spike_file<global_policy>;
 void banner();
 std::unique_ptr<recipe> make_recipe(const io::cl_options&, const probe_distribution&);
@@ -122,7 +122,7 @@ int main(int argc, char** argv) {
 
         // Attach samplers to all probes
         std::vector<std::unique_ptr<sample_trace_type>> traces;
-        const model_type::time_type sample_dt = 0.1;
+        const time_type sample_dt = 0.1;
         for (auto probe: m.probes()) {
             if (options.trace_max_gid && probe.id.gid>*options.trace_max_gid) {
                 continue;
diff --git a/src/cell_group.hpp b/src/cell_group.hpp
index 2148a0b5bf90f5c86b8f75af691e08069808b1ce..f6e4a5000450fe7409b509aff9a4ab23bd03fe3c 100644
--- a/src/cell_group.hpp
+++ b/src/cell_group.hpp
@@ -28,7 +28,6 @@ public:
     using size_type  = typename lowered_cell_type::value_type;
     using source_id_type = cell_member_type;
 
-    using time_type = spike::time_type;
     using sampler_function = std::function<util::optional<time_type>(time_type, double)>;
 
     cell_group() = default;
@@ -86,7 +85,7 @@ public:
 
         lowered_.setup_integration(tfinal, dt);
 
-        std::vector<sample_event<time_type>> requeue_sample_events;
+        std::vector<sample_event> requeue_sample_events;
         while (!lowered_.integration_complete()) {
             // Take any pending samples.
             // TODO: Placeholder: this will be replaced by a backend polling implementation.
@@ -145,8 +144,7 @@ public:
         PL();
     }
 
-    template <typename R>
-    void enqueue_events(const R& events) {
+    void enqueue_events(const std::vector<postsynaptic_spike_event>& events) {
         for (auto& e: events) {
             events_.push(e);
         }
@@ -167,7 +165,7 @@ public:
     void add_sampler(cell_member_type probe_id, sampler_function s, time_type start_time = 0) {
         auto handle = get_probe_handle(probe_id);
 
-        using size_type = sample_event<time_type>::size_type;
+        using size_type = sample_event::size_type;
         auto sampler_index = size_type(samplers_.size());
         samplers_.push_back({handle, probe_id.gid, s});
         sampler_start_times_.push_back(start_time);
@@ -192,10 +190,10 @@ private:
     event_binner binner_;
 
     // Pending events to be delivered.
-    event_queue<postsynaptic_spike_event<time_type>> events_;
+    event_queue<postsynaptic_spike_event> events_;
 
     // Pending samples to be taken.
-    event_queue<sample_event<time_type>> sample_events_;
+    event_queue<sample_event> sample_events_;
     std::vector<time_type> sampler_start_times_;
 
     // Handles for accessing lowered cell.
@@ -263,7 +261,7 @@ private:
     void reset_samplers() {
         // clear all pending sample events and reset to start at time 0
         sample_events_.clear();
-        using size_type = sample_event<time_type>::size_type;
+        using size_type = sample_event::size_type;
         for(size_type i=0; i<samplers_.size(); ++i) {
             sample_events_.push({i, sampler_start_times_[i]});
         }
diff --git a/src/common_types.hpp b/src/common_types.hpp
index 6bd3517b9216285c2896473e82fbdb6e2f1cfa64..c6731a2b9808c390cc8aa2bfa0098f141f704f46 100644
--- a/src/common_types.hpp
+++ b/src/common_types.hpp
@@ -49,6 +49,10 @@ struct cell_member_type {
 
 DEFINE_LEXICOGRAPHIC_ORDERING(cell_member_type,(a.gid,a.index),(b.gid,b.index))
 
+// For storing time values [ms]
+
+using time_type = float;
+
 } // namespace mc
 } // namespace nest
 
diff --git a/src/communication/communicator.hpp b/src/communication/communicator.hpp
index ffaad887ca2952a4ae19fd55f8c111c28fc1d173..ba671b4ce19dd05ba4d392b5aadbc2df5a1e62eb 100644
--- a/src/communication/communicator.hpp
+++ b/src/communication/communicator.hpp
@@ -7,6 +7,7 @@
 #include <functional>
 
 #include <algorithms.hpp>
+#include <common_types.hpp>
 #include <connection.hpp>
 #include <communication/gathered_vector.hpp>
 #include <event_queue.hpp>
@@ -34,11 +35,10 @@ template <typename CommunicationPolicy>
 class communicator {
 public:
     using communication_policy_type = CommunicationPolicy;
-    using time_type = spike::time_type;
 
     /// per-cell group lists of events to be delivered
     using event_queue =
-        std::vector<postsynaptic_spike_event<time_type>>;
+        std::vector<postsynaptic_spike_event>;
 
     using gid_partition_type =
         util::partition_range<std::vector<cell_gid_type>::const_iterator>;
diff --git a/src/connection.hpp b/src/connection.hpp
index e5c2252160332ca25c8cbcd0f98e0d7d255b1b97..e65100a97c01291ab37eeba4670710a4ff65ff0d 100644
--- a/src/connection.hpp
+++ b/src/connection.hpp
@@ -11,8 +11,6 @@ namespace mc {
 
 class connection {
 public:
-    using time_type = spike::time_type;
-
     connection() = default;
     connection(cell_member_type src, cell_member_type dest, float w, time_type d) :
         source_(src),
@@ -27,7 +25,7 @@ public:
     cell_member_type source() const { return source_; }
     cell_member_type destination() const { return destination_; }
 
-    postsynaptic_spike_event<time_type> make_event(const spike& s) {
+    postsynaptic_spike_event make_event(const spike& s) {
         return {destination_, s.time + delay_, weight_};
     }
 
diff --git a/src/event_binner.cpp b/src/event_binner.cpp
index 6279db9b26e799387b9f3fdb580afc8a09347c3a..278f7f5153fc67604fa0abce468821b7de40a632 100644
--- a/src/event_binner.cpp
+++ b/src/event_binner.cpp
@@ -16,8 +16,7 @@ void event_binner::reset() {
     last_event_times_.clear();
 }
 
-event_binner::time_type
-event_binner::bin(cell_gid_type id, time_type t, time_type t_min) {
+time_type event_binner::bin(cell_gid_type id, time_type t, time_type t_min) {
     time_type t_binned = t;
 
     switch (policy_) {
@@ -43,7 +42,7 @@ event_binner::bin(cell_gid_type id, time_type t, time_type t_min) {
     return std::max(t_binned, t_min);
 }
 
-util::optional<event_binner::time_type>
+util::optional<time_type>
 event_binner::last_event_time(cell_gid_type id) {
     auto it = last_event_times_.find(id);
     return it==last_event_times_.end()? util::nothing: util::just(it->second);
diff --git a/src/event_binner.hpp b/src/event_binner.hpp
index a18b9bb0ce3f6d6fa2a14799321794b98d634e01..f9ed628281a48dbb1b36614f767bdd4f82957c0b 100644
--- a/src/event_binner.hpp
+++ b/src/event_binner.hpp
@@ -18,8 +18,6 @@ enum class binning_kind {
 
 class event_binner {
 public:
-    using time_type = spike::time_type;
-
     event_binner(): policy_(binning_kind::none), bin_interval_(0) {}
 
     event_binner(binning_kind policy, time_type bin_interval):
diff --git a/src/event_queue.hpp b/src/event_queue.hpp
index f26a60c52a954c7566d1892647f740e3e26366fb..c796da31d7f17b9c3144bd8024dadacbc86d81a8 100644
--- a/src/event_queue.hpp
+++ b/src/event_queue.hpp
@@ -20,18 +20,13 @@ namespace mc {
  * Time values must be well ordered with respect to `operator>`.
  */
 
-template <typename Time>
 struct postsynaptic_spike_event {
-    using time_type = Time;
-
     cell_member_type target;
     time_type time;
     float weight;
 };
 
-template <typename Time>
 struct sample_event {
-    using time_type = Time;
     using size_type = std::uint32_t;
 
     size_type sampler_index;
@@ -58,7 +53,7 @@ template <typename Event>
 class event_queue {
 public :
     using value_type = Event;
-    using time_type = impl::event_time_type<Event>;
+    using event_time_type = impl::event_time_type<Event>;
 
     event_queue() {}
 
@@ -79,7 +74,7 @@ public :
     }
 
     // Return time t of head of queue if `t_until` > `t`.
-    util::optional<time_type> time_if_before(const time_type& t_until) {
+    util::optional<event_time_type> time_if_before(const event_time_type& t_until) {
         if (queue_.empty()) {
             return util::nothing;
         }
@@ -105,7 +100,7 @@ public :
     }
 
     // Pop and return top event `ev` of queue if `t_until` > `event_time(ev)`.
-    util::optional<value_type> pop_if_before(const time_type& t_until) {
+    util::optional<value_type> pop_if_before(const event_time_type& t_until) {
         using ::nest::mc::event_time;
         return pop_if(
             [&t_until](const value_type& ev) { return t_until > event_time(ev); }
@@ -113,7 +108,7 @@ public :
     }
 
     // Pop and return top event `ev` of queue unless `event_time(ev)` > `t_until`
-    util::optional<value_type> pop_if_not_after(const time_type& t_until) {
+    util::optional<value_type> pop_if_not_after(const event_time_type& t_until) {
         using ::nest::mc::event_time;
         return pop_if(
             [&t_until](const value_type& ev) { return !(event_time(ev) > t_until); }
@@ -143,8 +138,8 @@ private:
 } // namespace nest
 } // namespace mc
 
-template <typename T>
-inline std::ostream& operator<<(std::ostream& o, const nest::mc::postsynaptic_spike_event<T>& e)
+inline std::ostream& operator<<(
+    std::ostream& o, const nest::mc::postsynaptic_spike_event& e)
 {
     return o << "event[" << e.target << "," << e.time << "," << e.weight << "]";
 }
diff --git a/src/model.hpp b/src/model.hpp
index 99448000254ae4b9f5c79af3257b4120462d5c68..837ddc8d3b71944ce39f1f7046c4dd26883820ce 100644
--- a/src/model.hpp
+++ b/src/model.hpp
@@ -28,7 +28,6 @@ class model {
 public:
     // FIXME: this is an intermediate step to remove the template parameter from model
     using cell_group_type = cell_group<Cell>; // FIXME
-    using time_type = typename spike::time_type;
     using communicator_type = communication::communicator<communication::global_policy>;
     using spike_export_function = std::function<void(const std::vector<spike>&)>;
 
diff --git a/src/spike.hpp b/src/spike.hpp
index 6675605dbfc18769ace33acac78e7bcaa681e61a..8a883f01dbb486dd47d34efb960dd9bbd7a43fef 100644
--- a/src/spike.hpp
+++ b/src/spike.hpp
@@ -8,10 +8,9 @@
 namespace nest {
 namespace mc {
 
-template <typename I, typename Time>
+template <typename I>
 struct basic_spike {
     using id_type = I;
-    using time_type = Time;
 
     id_type source = id_type{};
     time_type time = -1;
@@ -24,21 +23,21 @@ struct basic_spike {
 };
 
 /// Standard specialization:
-using spike = basic_spike<cell_member_type, float>;
+using spike = basic_spike<cell_member_type>;
 
 } // namespace mc
 } // namespace nest
 
 // Custom stream operator for printing nest::mc::spike<> values.
-template <typename I, typename T>
-std::ostream& operator<<(std::ostream& o, nest::mc::basic_spike<I, T> s) {
+template <typename I>
+std::ostream& operator<<(std::ostream& o, nest::mc::basic_spike<I> s) {
     return o << "spike[t " << s.time << ", src " << s.source << "]";
 }
 
 /// Less than comparison operator for nest::mc::spike<> values:
 /// spikes are ordered by spike time, for use in sorting and queueing.
-template <typename I, typename T>
-bool operator<(nest::mc::basic_spike<I, T> lhs, nest::mc::basic_spike<I, T> rhs) {
+template <typename I>
+bool operator<(nest::mc::basic_spike<I> lhs, nest::mc::basic_spike<I> rhs) {
     return lhs.time < rhs.time;
 }
 
diff --git a/tests/unit/test_event_queue.cpp b/tests/unit/test_event_queue.cpp
index 60a8da476221f7595657be304fc6c8e67f6fb111..de3762d26ce714bfb7e9bfcc8f4f204d6594bdc0 100644
--- a/tests/unit/test_event_queue.cpp
+++ b/tests/unit/test_event_queue.cpp
@@ -8,7 +8,7 @@
 using namespace nest::mc;
 
 TEST(event_queue, push) {
-    using ps_event_queue = event_queue<postsynaptic_spike_event<float>>;
+    using ps_event_queue = event_queue<postsynaptic_spike_event>;
 
     ps_event_queue q;
 
@@ -29,7 +29,7 @@ TEST(event_queue, push) {
 }
 
 TEST(event_queue, pop_if_before) {
-    using ps_event_queue = event_queue<postsynaptic_spike_event<float>>;
+    using ps_event_queue = event_queue<postsynaptic_spike_event>;
 
     cell_member_type target[4] = {
         {1u, 0u},
@@ -38,7 +38,7 @@ TEST(event_queue, pop_if_before) {
         {2u, 3u}
     };
 
-    postsynaptic_spike_event<float> events[] = {
+    postsynaptic_spike_event events[] = {
         {target[0], 1.f, 2.f},
         {target[1], 2.f, 2.f},
         {target[2], 3.f, 2.f},
diff --git a/tests/validation/validate_synapses.hpp b/tests/validation/validate_synapses.hpp
index a6ee35e90f271866563a69d33d8ff62d3320cb95..cee900624b277da18f2b369a73af70b32bea42fd 100644
--- a/tests/validation/validate_synapses.hpp
+++ b/tests/validation/validate_synapses.hpp
@@ -39,7 +39,7 @@ void run_synapse_test(
     add_common_voltage_probes(c);
 
     // injected spike events
-    postsynaptic_spike_event<float> synthetic_events[] = {
+    std::vector<postsynaptic_spike_event> synthetic_events = {
         {{0u, 0u}, 10.0, 0.04},
         {{0u, 0u}, 20.0, 0.04},
         {{0u, 0u}, 40.0, 0.04}