diff --git a/arbor/arbexcept.cpp b/arbor/arbexcept.cpp
index e27f04fad7501d7e5358eca41fc10e2c7303c602..2a384b517110c12fa50a77f9a3a6eb0d91cdcbd6 100644
--- a/arbor/arbexcept.cpp
+++ b/arbor/arbexcept.cpp
@@ -43,22 +43,12 @@ bad_connection_source_lid::bad_connection_source_lid(cell_gid_type gid, cell_lid
     gid(gid), src_lid(src_lid), num_sources(num_sources)
 {}
 
-bad_connection_target_gid::bad_connection_target_gid(cell_gid_type gid, cell_gid_type tgt_gid):
-    arbor_exception(pprintf("Model building error on cell {}: connection target gid {} has to match cell gid {}].", gid, tgt_gid, gid)),
-    gid(gid), tgt_gid(tgt_gid)
-{}
-
 bad_connection_target_lid::bad_connection_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets):
     arbor_exception(pprintf("Model building error on cell {}: connection target index {} is out of range. Cell {} has {} targets", gid, tgt_lid, gid, num_targets) +
                     (num_targets ? pprintf(", in the range [{}:{}].", 0, num_targets-1) : ".")),
     gid(gid), tgt_lid(tgt_lid), num_targets(num_targets)
 {}
 
-bad_event_generator_target_gid::bad_event_generator_target_gid(cell_gid_type gid, cell_gid_type tgt_gid):
-    arbor_exception(pprintf("Model building error on cell {}: event_generator target gid {} has to match cell gid {}].", gid, tgt_gid, gid)),
-    gid(gid), tgt_gid(tgt_gid)
-{}
-
 bad_event_generator_target_lid::bad_event_generator_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets):
     arbor_exception(pprintf("Model building error on cell {}: event_generator target index {} is out of range. Cell {} has {} targets", gid, tgt_lid, gid, num_targets) +
                     (num_targets ? pprintf(", in the range [{}:{}].", 0, num_targets-1) : ".")),
@@ -81,13 +71,6 @@ gj_unsupported_domain_decomposition::gj_unsupported_domain_decomposition(cell_gi
     gid_1(gid_1)
 {}
 
-bad_gj_connection_gid::bad_gj_connection_gid(cell_gid_type gid, cell_gid_type site_0, cell_gid_type site_1):
-    arbor_exception(pprintf("Model building error on cell {}: recipe::gap_junctions_on(gid={}) -> cell {} <-> cell{}: one of the sites must be on the cell with gid = {})", gid, gid, site_0, site_1, gid)),
-    gid(gid),
-    site_0(site_0),
-    site_1(site_1)
-{}
-
 bad_gj_connection_lid::bad_gj_connection_lid(cell_gid_type gid, cell_member_type site):
     arbor_exception(pprintf("Model building error on cell {}: gap junction index {} on cell {} does not exist)", gid, site.gid, site.index)),
     gid(gid),
diff --git a/arbor/communication/communicator.cpp b/arbor/communication/communicator.cpp
index 032f09c43416a3f15d8f170175009fba4f4ccf34..b93638f82836d42484b1933341a5c81ed1e87790 100644
--- a/arbor/communication/communicator.cpp
+++ b/arbor/communication/communicator.cpp
@@ -87,11 +87,8 @@ communicator::communicator(const recipe& rec,
             if (c.source.index >= num_sources) {
                 throw arb::bad_connection_source_lid(cell.gid, c.source.index, num_sources);
             }
-            if (c.dest.gid != cell.gid) {
-                throw arb::bad_connection_target_gid(cell.gid, c.dest.gid);
-            }
-            if (c.dest.index >= num_targets) {
-                throw arb::bad_connection_target_lid(cell.gid, c.dest.index, num_targets);
+            if (c.dest >= num_targets) {
+                throw arb::bad_connection_target_lid(cell.gid, c.dest, num_targets);
             }
             const auto src = dom_dec.gid_domain(c.source.gid);
             src_domains.push_back(src);
diff --git a/arbor/connection.hpp b/arbor/connection.hpp
index 4a9fe0fc35bb8341cceaac65fbdc53de73b30629..05be955685a27c19bfd0addb4cdc073ec3c19c96 100644
--- a/arbor/connection.hpp
+++ b/arbor/connection.hpp
@@ -11,7 +11,7 @@ class connection {
 public:
     connection() = default;
     connection( cell_member_type src,
-                cell_member_type dest,
+                cell_lid_type dest,
                 float w,
                 float d,
                 cell_gid_type didx=cell_gid_type(-1)):
@@ -26,7 +26,7 @@ public:
     time_type delay() const { return delay_; }
 
     cell_member_type source() const { return source_; }
-    cell_member_type destination() const { return destination_; }
+    cell_lid_type destination() const { return destination_; }
     cell_size_type index_on_domain() const { return index_on_domain_; }
 
     spike_event make_event(const spike& s) {
@@ -35,7 +35,7 @@ public:
 
 private:
     cell_member_type source_;
-    cell_member_type destination_;
+    cell_lid_type destination_;
     float weight_;
     float delay_;
     cell_size_type index_on_domain_;
diff --git a/arbor/fvm_lowered_cell_impl.hpp b/arbor/fvm_lowered_cell_impl.hpp
index 6086383fcf2483e62d512fc5a27dfabda90aafc9..8bdc287daa9c2e87dff461d0757b43bd4694d598 100644
--- a/arbor/fvm_lowered_cell_impl.hpp
+++ b/arbor/fvm_lowered_cell_impl.hpp
@@ -644,20 +644,14 @@ std::vector<fvm_gap_junction> fvm_lowered_cell_impl<Backend>::fvm_gap_junctions(
     for (auto gid: gids) {
         auto gj_list = rec.gap_junctions_on(gid);
         for (auto g: gj_list) {
-            if (gid != g.local.gid && gid != g.peer.gid) {
-                throw arb::bad_gj_connection_gid(gid, g.local.gid, g.peer.gid);
-            }
-            if (g.local.index >= gid_to_cvs[g.local.gid].size()) {
-                throw arb::bad_gj_connection_lid(gid, g.local);
+            if (g.local >= gid_to_cvs[gid].size()) {
+                throw arb::bad_gj_connection_lid(gid, {gid, g.local});
             }
             if (g.peer.index >= gid_to_cvs[g.peer.gid].size()) {
                 throw arb::bad_gj_connection_lid(gid, g.peer);
             }
-            auto cv0 = gid_to_cvs[g.local.gid][g.local.index];
+            auto cv0 = gid_to_cvs[gid][g.local];
             auto cv1 = gid_to_cvs[g.peer.gid][g.peer.index];
-            if (gid != g.local.gid) {
-                std::swap(cv0, cv1);
-            }
             v.push_back(fvm_gap_junction(std::make_pair(cv0, cv1), g.ggap * 1e3 / D.cv_area[cv0]));
         }
     }
@@ -694,18 +688,13 @@ fvm_size_type fvm_lowered_cell_impl<Backend>::fvm_intdom(
             cell_to_intdom[gid_to_loc[g]] = intdom_id;
 
             for (auto gj: rec.gap_junctions_on(g)) {
-                cell_gid_type peer =
-                        gj.local.gid==g? gj.peer.gid:
-                        gj.peer.gid==g?  gj.local.gid:
-                        throw bad_cell_description(cell_kind::cable, g);
-
-                if (!gid_to_loc.count(peer)) {
-                    throw gj_unsupported_domain_decomposition(g, peer);
+                if (!gid_to_loc.count(gj.peer.gid)) {
+                    throw gj_unsupported_domain_decomposition(g, gj.peer.gid);
                 }
 
-                if (!visited.count(peer)) {
-                    visited.insert(peer);
-                    intdomq.push(peer);
+                if (!visited.count(gj.peer.gid)) {
+                    visited.insert(gj.peer.gid);
+                    intdomq.push(gj.peer.gid);
                 }
             }
         }
diff --git a/arbor/include/arbor/arbexcept.hpp b/arbor/include/arbor/arbexcept.hpp
index 814c628fc98e96e405727cf2ff680f95eb627ff7..2cc0c5ed2d9c872e5bea074ceffa7f2daf82fada 100644
--- a/arbor/include/arbor/arbexcept.hpp
+++ b/arbor/include/arbor/arbexcept.hpp
@@ -67,11 +67,6 @@ struct bad_connection_source_lid: arbor_exception {
     cell_size_type num_sources;
 };
 
-struct bad_connection_target_gid: arbor_exception {
-    bad_connection_target_gid(cell_gid_type gid, cell_gid_type tgt_gid);
-    cell_gid_type gid, tgt_gid;
-};
-
 struct bad_connection_target_lid: arbor_exception {
     bad_connection_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets);
     cell_gid_type gid;
@@ -79,11 +74,6 @@ struct bad_connection_target_lid: arbor_exception {
     cell_size_type num_targets;
 };
 
-struct bad_event_generator_target_gid: arbor_exception {
-    bad_event_generator_target_gid(cell_gid_type gid, cell_gid_type tgt_gid);
-    cell_gid_type gid, tgt_gid;
-};
-
 struct bad_event_generator_target_lid: arbor_exception {
     bad_event_generator_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets);
     cell_gid_type gid;
@@ -106,11 +96,6 @@ struct gj_kind_mismatch: arbor_exception {
     cell_gid_type gid_0, gid_1;
 };
 
-struct bad_gj_connection_gid: arbor_exception {
-    bad_gj_connection_gid(cell_gid_type gid, cell_gid_type site_0, cell_gid_type site_1);
-    cell_gid_type gid, site_0, site_1;
-};
-
 struct bad_gj_connection_lid: arbor_exception {
     bad_gj_connection_lid(cell_gid_type gid, cell_member_type site);
     cell_gid_type gid;
diff --git a/arbor/include/arbor/event_generator.hpp b/arbor/include/arbor/event_generator.hpp
index 4e526b58eb7c8f3460b724cb4c114fe148cd3757..95a524522ef695bd736c36d0d341de7e3483d08e 100644
--- a/arbor/include/arbor/event_generator.hpp
+++ b/arbor/include/arbor/event_generator.hpp
@@ -68,7 +68,7 @@ struct empty_generator {
     event_seq events(time_type, time_type) {
         return {nullptr, nullptr};
     }
-    std::vector<cell_member_type> targets() {
+    std::vector<cell_lid_type> targets() {
         return {};
     };
 };
@@ -102,7 +102,7 @@ public:
         return impl_->events(t0, t1);
     }
 
-    std::vector<cell_member_type> targets() const {
+    std::vector<cell_lid_type> targets() const {
         return impl_->targets();
     }
 
@@ -110,7 +110,7 @@ private:
     struct interface {
         virtual void reset() = 0;
         virtual event_seq events(time_type, time_type) = 0;
-        virtual std::vector<cell_member_type> targets() = 0;
+        virtual std::vector<cell_lid_type> targets() = 0;
         virtual std::unique_ptr<interface> clone() = 0;
         virtual ~interface() {}
     };
@@ -126,7 +126,7 @@ private:
             return wrapped.events(t0, t1);
         }
 
-        std::vector<cell_member_type> targets() override {
+        std::vector<cell_lid_type> targets() override {
             return wrapped.targets();
         }
 
@@ -148,7 +148,7 @@ private:
 // a provided time schedule.
 
 struct schedule_generator {
-    schedule_generator(cell_member_type target, float weight, schedule sched):
+    schedule_generator(cell_lid_type target, float weight, schedule sched):
         target_(target), weight_(weight), sched_(std::move(sched))
     {}
 
@@ -169,13 +169,13 @@ struct schedule_generator {
         return {events_.data(), events_.data()+events_.size()};
     }
 
-    std::vector<cell_member_type> targets() {
+    std::vector<cell_lid_type> targets() {
         return {target_};
     }
 
 private:
     pse_vector events_;
-    cell_member_type target_;
+    cell_lid_type target_;
     float weight_;
     schedule sched_;
 };
@@ -183,7 +183,7 @@ private:
 // Generate events at integer multiples of dt that lie between tstart and tstop.
 
 inline event_generator regular_generator(
-    cell_member_type target,
+    cell_lid_type target,
     float weight,
     time_type tstart,
     time_type dt,
@@ -194,7 +194,7 @@ inline event_generator regular_generator(
 
 template <typename RNG>
 inline event_generator poisson_generator(
-    cell_member_type target,
+    cell_lid_type target,
     float weight,
     time_type tstart,
     time_type rate_kHz,
@@ -237,8 +237,8 @@ struct explicit_generator {
         return {lb, ub};
     }
 
-    std::vector<cell_member_type> targets() {
-        std::vector<cell_member_type> tgts;
+    std::vector<cell_lid_type> targets() {
+        std::vector<cell_lid_type> tgts;
         std::transform(events_.begin(), events_.end(), std::back_inserter(tgts), [](auto&& e){ return e.target;});
         return tgts;
     }
diff --git a/arbor/include/arbor/recipe.hpp b/arbor/include/arbor/recipe.hpp
index 3e8d834f9a2f27d82440ce30f580036b2951fcfe..63fe1a215d446acb1201644fc7cbb468adc53ea3 100644
--- a/arbor/include/arbor/recipe.hpp
+++ b/arbor/include/arbor/recipe.hpp
@@ -40,26 +40,25 @@ struct probe_info {
 struct cell_connection {
     // Connection end-points are represented by pairs
     // (cell index, source/target index on cell).
-    using cell_connection_endpoint = cell_member_type;
 
-    cell_connection_endpoint source;
-    cell_connection_endpoint dest;
+    cell_member_type source;
+    cell_lid_type dest;
 
     float weight;
     float delay;
 
-    cell_connection(cell_connection_endpoint src, cell_connection_endpoint dst, float w, float d):
+    cell_connection(cell_member_type src, cell_lid_type dst, float w, float d):
         source(src), dest(dst), weight(w), delay(d)
     {}
 };
 
 struct gap_junction_connection {
-    cell_member_type local;
     cell_member_type peer;
+    cell_lid_type local;
     double ggap;
 
-    gap_junction_connection(cell_member_type local, cell_member_type peer, double g):
-            local(local), peer(peer), ggap(g) {}
+    gap_junction_connection(cell_member_type peer, cell_lid_type local, double g):
+        peer(peer), local(local), ggap(g) {}
 };
 
 class recipe {
diff --git a/arbor/include/arbor/simulation.hpp b/arbor/include/arbor/simulation.hpp
index c26d022577f47837538686ff68953c79c8b3d74c..1f4afc6926803bb516e54f1af564854096dd74cb 100644
--- a/arbor/include/arbor/simulation.hpp
+++ b/arbor/include/arbor/simulation.hpp
@@ -59,7 +59,7 @@ public:
     // Add events directly to targets.
     // Must be called before calling simulation::run, and must contain events that
     // are to be delivered at or after the current simulation time.
-    void inject_events(const pse_vector& events);
+    void inject_events(const cse_vector& events);
 
     ~simulation();
 
diff --git a/arbor/include/arbor/spike_event.hpp b/arbor/include/arbor/spike_event.hpp
index 2b72314c3ca3fce11f8dc61c09391f15fc8962e1..102f3c42403dc1402f5b1cfda2e0a2b399219c30 100644
--- a/arbor/include/arbor/spike_event.hpp
+++ b/arbor/include/arbor/spike_event.hpp
@@ -11,7 +11,7 @@ namespace arb {
 // Events delivered to targets on cells with a cell group.
 
 struct spike_event {
-    cell_member_type target;
+    cell_lid_type target;
     time_type time;
     float weight;
 
@@ -26,6 +26,13 @@ struct spike_event {
 
 using pse_vector = std::vector<spike_event>;
 
+struct cell_spike_events {
+    cell_gid_type target;
+    pse_vector events;
+};
+
+using cse_vector = std::vector<cell_spike_events>;
+
 std::ostream& operator<<(std::ostream&, const spike_event&);
 
 } // namespace arb
diff --git a/arbor/mc_cell_group.cpp b/arbor/mc_cell_group.cpp
index 395f426e4b918f375caaf42315298f6476cd8962..3a0a27ed0a26ee0ba564a2a23bbe41d573f415d0 100644
--- a/arbor/mc_cell_group.cpp
+++ b/arbor/mc_cell_group.cpp
@@ -400,7 +400,7 @@ void mc_cell_group::advance(epoch ep, time_type dt, const event_lane_subrange& e
             for (auto e: lane) {
                 if (e.time>=ep.t1) break;
                 e.time = binners_[lid].bin(e.time, tstart);
-                auto h = target_handles_[target_handle_divisions_[lid]+e.target.index];
+                auto h = target_handles_[target_handle_divisions_[lid]+e.target];
                 auto ev = deliverable_event(e.time, h, e.weight);
                 staged_events_.push_back(ev);
                 count_staged++;
diff --git a/arbor/merge_events.cpp b/arbor/merge_events.cpp
index 53dd901ffb5377f088ae645b088d6ef57e3a7060..90241cad646a2d1d55a20ded0501c45c488b6db5 100644
--- a/arbor/merge_events.cpp
+++ b/arbor/merge_events.cpp
@@ -17,7 +17,7 @@ namespace impl {
 // A postsynaptic spike event that has delivery time set to
 // terminal_time, used as a sentinel in `tourney_tree`.
 
-static constexpr spike_event terminal_pse{cell_member_type{0,0}, terminal_time, 0};
+static constexpr spike_event terminal_pse{0, terminal_time, 0};
 
 
 // The tournament tree data structure is used to merge k sorted lists of events.
diff --git a/arbor/partition_load_balance.cpp b/arbor/partition_load_balance.cpp
index e8fd413557355138f01db42c29b9d7e51f1b2644..f1f064b7957ec55f788e0f9e98d15ab85f853df7 100644
--- a/arbor/partition_load_balance.cpp
+++ b/arbor/partition_load_balance.cpp
@@ -92,14 +92,9 @@ domain_decomposition partition_load_balance(
                     // Adjacency list
                     auto conns = rec.gap_junctions_on(element);
                     for (auto c: conns) {
-                        if (element != c.local.gid && element != c.peer.gid) {
-                            throw bad_gj_connection_gid(element, c.local.gid, c.peer.gid);
-                        }
-                        cell_member_type other = c.local.gid == element ? c.peer : c.local;
-
-                        if (!visited.count(other.gid)) {
-                            visited.insert(other.gid);
-                            q.push(other.gid);
+                        if (!visited.count(c.peer.gid)) {
+                            visited.insert(c.peer.gid);
+                            q.push(c.peer.gid);
                         }
                     }
                 }
diff --git a/arbor/simulation.cpp b/arbor/simulation.cpp
index 3ed22957fe32d674e22d6a94f7e462a3673d0706..231c7d9a1cf37f968c09873812d461532c6a64b4 100644
--- a/arbor/simulation.cpp
+++ b/arbor/simulation.cpp
@@ -110,7 +110,7 @@ public:
 
     void set_binning_policy(binning_kind policy, time_type bin_interval);
 
-    void inject_events(const pse_vector& events);
+    void inject_events(const cse_vector& events);
 
     spike_export_function global_export_callback_;
     spike_export_function local_export_callback_;
@@ -208,11 +208,8 @@ simulation_state::simulation_state(
             auto num_targets = rec.num_targets(gid);
             for (const auto& g: event_gens) {
                 for (const auto& t: g.targets()) {
-                    if (t.gid != gid) {
-                        throw arb::bad_event_generator_target_gid(gid,  t.gid);
-                    }
-                    if (t.index >= num_targets) {
-                        throw arb::bad_event_generator_target_lid(gid, t.index, num_targets);
+                    if (t >= num_targets) {
+                        throw arb::bad_event_generator_target_lid(gid, t, num_targets);
                     }
                 }
             }
@@ -468,16 +465,18 @@ void simulation_state::set_binning_policy(binning_kind policy, time_type bin_int
         [&](cell_group_ptr& group) { group->set_binning_policy(policy, bin_interval); });
 }
 
-void simulation_state::inject_events(const pse_vector& events) {
+void simulation_state::inject_events(const cse_vector& events) {
     // Push all events that are to be delivered to local cells into the
     // pending event list for the event's target cell.
-    for (auto& e: events) {
-        if (e.time<epoch_.t1) {
-            throw bad_event_time(e.time, epoch_.t1);
-        }
-        // gid_to_local_ maps gid to index in local cells and of corresponding cell group.
-        if (auto lidx = util::value_by_key(gid_to_local_, e.target.gid)) {
-            pending_events_[lidx->cell_index].push_back(e);
+    for (auto& [gid, pse_vector]: events) {
+        for (auto& e: pse_vector) {
+            if (e.time < epoch_.t1) {
+                throw bad_event_time(e.time, epoch_.t1);
+            }
+            // gid_to_local_ maps gid to index in local cells and of corresponding cell group.
+            if (auto lidx = util::value_by_key(gid_to_local_, gid)) {
+                pending_events_[lidx->cell_index].push_back(e);
+            }
         }
     }
 }
@@ -537,7 +536,7 @@ void simulation::set_local_spike_callback(spike_export_function export_callback)
     impl_->local_export_callback_ = std::move(export_callback);
 }
 
-void simulation::inject_events(const pse_vector& events) {
+void simulation::inject_events(const cse_vector& events) {
     impl_->inject_events(events);
 }
 
diff --git a/arbor/symmetric_recipe.cpp b/arbor/symmetric_recipe.cpp
index 66b846f81e5aca781e336248ec9a95d2fd15e712..ccf9dec5083e79e41a3c0c7ea78db0268d0c0de1 100644
--- a/arbor/symmetric_recipe.cpp
+++ b/arbor/symmetric_recipe.cpp
@@ -39,7 +39,6 @@ std::vector<cell_connection> symmetric_recipe::connections_on(cell_gid_type i) c
 
     for (unsigned j = 0; j < conns.size(); j++) {
         conns[j].source.gid = (conns[j].source.gid + offset) % n_global;
-        conns[j].dest.gid = (conns[j].dest.gid + offset) % n_global;
     }
     return conns;
 }
diff --git a/doc/concepts/interconnectivity.rst b/doc/concepts/interconnectivity.rst
index 11caa96af5a38349dd18287e59e2214ab17a6947..73f9ca9cfac70f72a32d1005e725017fb54de761 100644
--- a/doc/concepts/interconnectivity.rst
+++ b/doc/concepts/interconnectivity.rst
@@ -53,8 +53,9 @@ A recipe lets you define which sites are connected to which.
 
       1. Create a **gap junction site** on two separate cells as part of their
          :ref:`cell descriptions <modelcelldesc>` in the :ref:`recipe <modelrecipe>`.
-      2. Declare the Gap Junction in the recipe: with two **gap junction sites** identified using :gen:`cell_member`
-         and a conductance in μS.
+      2. Declare the Gap Junction connections in the recipe: between a peer and local **gap junction site**
+         identified using :gen:`cell_member` and a conductance in μS. Two of these connections are needed,
+         on each of the peer and local cells.
 
    .. Note::
       Only cable cells support gap junctions as of now.
diff --git a/doc/cpp/interconnectivity.rst b/doc/cpp/interconnectivity.rst
index 266708a7503ea3a52da30ba40da2487f2f4af6be..3ac0dc43cee374f2db241c78e5bce6b0789d8667 100644
--- a/doc/cpp/interconnectivity.rst
+++ b/doc/cpp/interconnectivity.rst
@@ -9,18 +9,17 @@ Interconnectivity
     post-synaptic destination. The source is typically a threshold detector on
     a cell or a spike source. The destination is a synapse on the post-synaptic cell.
 
-    .. cpp:type:: cell_connection_endpoint = cell_member_type
+    The :cpp:member:`dest` does not include the gid of a cell, this is because a
+    :cpp:class:`cell_connection` is bound to the destination cell which means that the gid
+    is implicitly known.
 
-        Connection end-points are represented by pairs
-        (cell index, source/target index on cell).
+    .. cpp:member:: cell_member_type source
 
-    .. cpp:member:: cell_connection_endpoint source
+        Source end point, represented by the pair (cell gid, source index on the cell)
 
-        Source end point.
+    .. cpp:member:: cell_lid_type dest
 
-    .. cpp:member:: cell_connection_endpoint dest
-
-        Destination end point.
+        Destination target index on the cell, target cell's gid is implicitly known.
 
     .. cpp:member:: float weight
 
@@ -36,16 +35,25 @@ Interconnectivity
 
 .. cpp:class:: gap_junction_connection
 
-    Describes a gap junction between two gap junction sites.
-    Gap junction sites are represented by :cpp:type:cell_member_type.
+    Describes a gap junction between two gap junction sites. The :cpp:member:`local` site does not include
+    the gid of a cell, this is because a :cpp:class:`gap_junction_connection` is bound to the local
+    cell which means that the gid is implicitly known.
 
-    .. cpp:member:: cell_member_type local
+    .. note::
 
-        gap junction site: one half of the gap junction connection.
+       A bidirectional gap-junction between two cells ``c0`` and ``c1`` requires two
+       :cpp:class:`gap_junction_connection` objects to be constructed: one where ``c0`` is the
+       :cpp:member:`local` site, and ``c1`` is the :cpp:member:`peer` site; and another where ``c1`` is the
+       :cpp:member:`local` site, and ``c0`` is the :cpp:member:`peer` site. If :cpp:member:`ggap` is equal
+       in both connections, a symmetric gap-junction is formed, other wise the gap-junction is asymmetric.
 
     .. cpp:member:: cell_member_type peer
 
-        gap junction site: other half of the gap junction connection.
+        Peer gap junction site, represented by the pair (cell gid, gap junction site index on the cell)
+
+    .. cpp:member:: cell_lid_type local
+
+        Local gap junction site index on the cell, the gid of the local site's cell is implicitly known.
 
     .. cpp:member:: float ggap
 
diff --git a/doc/cpp/recipe.rst b/doc/cpp/recipe.rst
index a71c290f38b11e24897066d0ae6997234d3cc3fc..5660894e4f66f67976cc93924b4aad0040feb75a 100644
--- a/doc/cpp/recipe.rst
+++ b/doc/cpp/recipe.rst
@@ -74,8 +74,8 @@ Recipe
     .. cpp:function:: virtual std::vector<cell_connection> connections_on(cell_gid_type gid) const
 
         Returns a list of all the **incoming** connections for `gid` .
-        Each connection ``con`` should have post-synaptic target ``con.dest.gid`` that matches
-        the argument :cpp:any:`gid`, and a valid synapse id ``con.dest.index`` on `gid`.
+        Each connection ``con`` should have a valid synapse id ``con.dest`` on the post-synaptic target `gid`,
+        and a valid source id ``con.source.index`` on the pre-synaptic source ``con.source.gid``.
         See :cpp:type:`cell_connection`.
 
         By default returns an empty list.
@@ -83,9 +83,8 @@ Recipe
     .. cpp:function:: virtual std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const
 
         Returns a list of all the gap junctions connected to `gid`.
-        Each gap junction ``gj`` should have one of the two gap junction sites ``gj.local.gid`` or
-        ``gj.peer.gid`` matching the argument :cpp:any:`gid`, and the corresponding synapse id
-        ``gj.local.index`` or ``gj.peer.index`` should be valid on `gid`.
+        Each gap junction ``gj`` should have a valid gap junction site id ``gj.local`` on ``gid``,
+        and a valid gap junction site id ``gj.peer.index`` on ``gj.peer.gid``.
         See :cpp:type:`gap_junction_connection`.
 
         By default returns an empty list.
diff --git a/doc/python/cell.rst b/doc/python/cell.rst
index ca1d1df158e14c8bbd22686051f1053dbca37d0c..e89d472f3f6749e1cb229f2bb436d5a975fb3093 100644
--- a/doc/python/cell.rst
+++ b/doc/python/cell.rst
@@ -23,7 +23,7 @@ The types defined below are used as identifiers for cells and members of cell-lo
         An example is uniquely identifying a synapse in the model.
         Each synapse has a post-synaptic cell (with :attr:`gid`), and an :attr:`index` into the set of synapses on the post-synaptic cell.
 
-        Lexographically ordered by :attr:`gid`, then :attr:`index`.
+        Lexicographically ordered by :attr:`gid`, then :attr:`index`.
 
     .. attribute:: gid
 
diff --git a/doc/python/interconnectivity.rst b/doc/python/interconnectivity.rst
index 430496f28d9c7bf5c28e073d783f1bff3840ac8f..944825a2a981abe120a2efefc41bfe0a839180a4 100644
--- a/doc/python/interconnectivity.rst
+++ b/doc/python/interconnectivity.rst
@@ -10,6 +10,9 @@ Interconnectivity
     Describes a connection between two cells, defined by source and destination end points (that is pre-synaptic and post-synaptic respectively),
     a connection weight and a delay time.
 
+    The :attr:`dest` does not include the gid of a cell, this is because a :class:`arbor.connection` is bound to the destination cell which means that the gid
+    is implicitly known.
+
     .. function:: connection(source, destination, weight, delay)
 
         Construct a connection between the :attr:`source` and the :attr:`dest` with a :attr:`weight` and :attr:`delay`.
@@ -20,7 +23,8 @@ Interconnectivity
 
     .. attribute:: dest
 
-        The destination end point of the connection (type: :class:`arbor.cell_member`, which can be initialized with a (gid, index) tuple).
+        The destination end point of the connection (type: :class:`arbor.cell_member.index` representing the index of the destination on the cell).
+        The gid of the cell is implicitly known.
 
     .. attribute:: weight
 
@@ -40,29 +44,43 @@ Interconnectivity
 
             import arbor
 
-            # construct a connection between cells (0,0) and (1,0) with weight 0.01 and delay of 10 ms.
-            src  = arbor.cell_member(0,0)
-            dest = arbor.cell_member(1,0)
-            w    = 0.01
-            d    = 10
-            con  = arbor.connection(src, dest, w, d)
+            def connections_on(gid):
+               # construct a connection from the 0th source index of cell 2 (2,0)
+               # to the 1st target index of cell gid (gid,1) with weight 0.01 and delay of 10 ms.
+               src  = arbor.cell_member(2,0)
+               dest = 1 # gid of the destination is is determined by the argument to `connections_on`
+               w    = 0.01
+               d    = 10
+               return [arbor.connection(src, dest, w, d)]
 
 .. class:: gap_junction_connection
 
-    Describes a gap junction between two gap junction sites.
-    Gap junction sites are represented by :class:`arbor.cell_member`.
+    Describes a gap junction between two gap junction sites. Gap junction sites are identified by :class:`arbor.cell_member`.
 
-    .. function::gap_junction_connection(local, peer, ggap)
+    The :attr:`local` site does not include the gid of a cell, this is because a :class:`arbor.gap_junction_connection` is bound to
+    the destination cell which means that the gid is implicitly known.
 
-        Construct a gap junction connection between :attr:`local` and :attr:`peer` with conductance :attr:`ggap`.
+    .. note::
 
-    .. attribute:: local
+       A bidirectional gap-junction between two cells ``c0`` and ``c1`` requires two
+       :class:`gap_junction_connection` objects to be constructed: one where ``c0`` is the
+       :attr:`local` site, and ``c1`` is the :attr:`peer` site; and another where ``c1`` is the
+       :attr:`local` site, and ``c0`` is the :attr:`peer` site. If :attr:`ggap` is equal
+       in both connections, a symmetric gap-junction is formed, other wise the gap-junction is asymmetric.
+
+    .. function::gap_junction_connection(peer, local, ggap)
 
-        The gap junction site: one half of the gap junction connection.
+        Construct a gap junction connection between :attr:`peer` and :attr:`local` with conductance :attr:`ggap`.
 
     .. attribute:: peer
 
-        The gap junction site: other half of the gap junction connection.
+        The gap junction site: the remote half of the gap junction connection (type: :class:`arbor.cell_member`,
+        which can be initialized with a (gid, index) tuple).
+
+    .. attribute:: local
+
+        The gap junction site: the local half of the gap junction connection (type: :class:`arbor.cell_member.index`, representing
+        the index of the local site on the cell). The gid of the cell is implicitly known.
 
     .. attribute:: ggap
 
diff --git a/doc/python/recipe.rst b/doc/python/recipe.rst
index 0a945d5f80f677e321cb236f292a0c29bdf0a472..ecdea890931c35597328758123c4c953228bc361 100644
--- a/doc/python/recipe.rst
+++ b/doc/python/recipe.rst
@@ -33,11 +33,11 @@ Recipe
 
     .. function:: cell_kind(gid)
 
-        The cell kind of the cell with global identifier :attr:`arbor.cell_member.gid` (return type: :class:`arbor.cell_kind`).
+        The cell kind of the cell with global identifier ``gid`` (return type: :class:`arbor.cell_kind`).
 
     .. function:: cell_description(gid)
 
-        A high level description of the cell with global identifier :attr:`arbor.cell_member.gid`,
+        A high level description of the cell with global identifier ``gid``,
         for example the morphology, synapses and ion channels required to build a multi-compartment neuron.
         The type used to describe a cell depends on the kind of the cell.
         The interface for querying the kind and description of a cell are separate
@@ -48,45 +48,43 @@ Recipe
 
     .. function:: connections_on(gid)
 
-        Returns a list of all the **incoming** connections to :attr:`arbor.cell_member.gid`.
-        Each connection should have post-synaptic target ``connection.dest.gid``
-        that matches the argument :attr:`arbor.cell_member.gid`,
-        and a valid synapse id ``connection.dest.index`` on :attr:`arbor.cell_member.gid`.
+        Returns a list of all the **incoming** connections to ``gid``.
+        Each connection should have a valid synapse id ``connection.dest`` on the post-synaptic target ``gid``,
+        and a valid source id ``connection.source.index`` on the pre-synaptic source ``connection.source.gid``.
         See :class:`connection`.
 
         By default returns an empty list.
 
     .. function:: gap_junctions_on(gid)
 
-        Returns a list of all the gap junctions connected to :attr:`arbor.cell_member.gid`.
-        Each gap junction ``gj`` should have one of the two gap junction sites ``gj.local.gid``
-        or ``gj.peer.gid`` matching the argument :attr:`arbor.cell_member.gid`,
-        and the corresponding synapse id ``gj.local.index`` or ``gj.peer.index`` should be valid on :attr:`arbor.cell_member.gid`.
+        Returns a list of all the gap junctions connected to ``gid``.
+        Each gap junction ``gj`` should have a valid gap junction site id ``gj.local`` on ``gid``,
+        and a valid gap junction site id ``gj.peer.index`` on ``gj.peer.gid``.
         See :class:`gap_junction_connection`.
 
         By default returns an empty list.
 
     .. function:: event_generators(gid)
 
-        A list of all the :class:`event_generator` s that are attached to :attr:`arbor.cell_member.gid`.
+        A list of all the :class:`event_generator` s that are attached to ``gid``.
 
         By default returns an empty list.
 
     .. function:: num_sources(gid)
 
-        The number of spike sources on :attr:`arbor.cell_member.gid`.
+        The number of spike sources on ``gid``.
 
         By default returns 0.
 
     .. function:: num_targets(gid)
 
-        The number of post-synaptic sites on :attr:`arbor.cell_member.gid`, which corresponds to the number of synapses.
+        The number of post-synaptic sites on ``gid``, which corresponds to the number of synapses.
 
         By default returns 0.
 
     .. function:: num_gap_junction_sites(gid)
 
-        Returns the number of gap junction sites on :attr:`arbor.cell_member.gid`.
+        Returns the number of gap junction sites on ``gid``.
 
         By default returns 0.
 
@@ -132,7 +130,7 @@ Event generator and schedules
 
     .. attribute:: target
 
-        The target synapse of type :class:`arbor.cell_member`.
+        The target synapse of type :class:`arbor.cell_member.index`.
 
     .. attribute:: weight
 
@@ -222,15 +220,16 @@ An example of an event generator reads as follows:
 
         # define a Poisson schedule with start time 1 ms, expected frequency of 5 Hz,
         # and the target cell's gid as seed
-        target = arbor.cell_member(0,0)
-        seed   = target.gid
-        tstart = 1
-        freq   = 0.005
-        sched  = arbor.poisson_schedule(tstart, freq, seed)
+        def event_generators(gid):
+            target = 0   # index of the synapse on target cell gid
+            seed   = gid
+            tstart = 1
+            freq   = 0.005
+            sched  = arbor.poisson_schedule(tstart, freq, seed)
 
-        # construct an event generator with this schedule on target cell and weight 0.1
-        w      = 0.1
-        gen    = arbor.event_generator(target, w, sched)
+            # construct an event generator with this schedule on target cell and weight 0.1
+            w = 0.1
+            return [arbor.event_generator(target, w, sched)]
 
 Example
 -------
@@ -280,13 +279,13 @@ helpers in cell_parameters and make_cable_cell for building cells are used.
                 src = (gid-1)%self.ncells
                 w = 0.01
                 d = 10
-                return [arbor.connection(arbor.cell_member(src,0), arbor.cell_member(gid,0), w, d)]
+                return [arbor.connection(arbor.cell_member(src,0), 0, w, d)]
 
             # Attach a generator to the first cell in the ring.
             def event_generators(self, gid):
                 if gid==0:
                     sched = arbor.explicit_schedule([1])
-                    return [arbor.event_generator(arbor.cell_member(0,0), 0.1, sched)]
+                    return [arbor.event_generator(0, 0.1, sched)]
                 return []
 
             def get_probes(self, id):
diff --git a/doc/tutorial/network_ring.rst b/doc/tutorial/network_ring.rst
index a7cbe4be120ec3000958715dc2d411717f31cdd7..d0db20cfe192b959ec64eef73dba2fdd8b98b51f 100644
--- a/doc/tutorial/network_ring.rst
+++ b/doc/tutorial/network_ring.rst
@@ -102,7 +102,9 @@ to :py:class:`arbor.connection` are the **source** and **target** of the connect
 cell index ``gid`` and the source or target index. (:term:`Remember <connection>` that sources and targets are
 separately indexed.)
 
-The two endpoints are of type :class:`arbor.cell_member`, and can be initialized with a ``(gid,index)`` tuple.
+The source endpoint has type :class:`arbor.cell_member`, and can be initialized with a ``(gid,index)`` tuple.
+The gid of the target end-point is implicitly known from the argument of :py:func:`arbor.recipe.connections_on`,
+Therefore, we only need to identify the index of the target on the cell using the :class:`arbor.cell_member.index` type.
 The cells have one synapse (step **3**), so the target endpoint has the 0th index. The cell has one
 spike generator (step **4**), so its source index is also 0.
 
diff --git a/example/bench/bench.cpp b/example/bench/bench.cpp
index ab5912e70ed54a00e08c9ba563de96eff7abf90d..43df04e0e828b30f92ceb4079cb77a09aaf079e3 100644
--- a/example/bench/bench.cpp
+++ b/example/bench/bench.cpp
@@ -134,7 +134,7 @@ public:
             arb::cell_gid_type src = dist(rng);
             if (src>=gid) ++src;
             // Note: target is {gid, 0}, i.e. the first (and only) target on the cell.
-            arb::cell_connection con({src, 0}, {gid, 0}, 1.f, params_.network.min_delay);
+            arb::cell_connection con({src, 0}, 0, 1.f, params_.network.min_delay);
             cons.push_back(con);
         }
 
diff --git a/example/brunel/brunel.cpp b/example/brunel/brunel.cpp
index 7f208844d08b79dcbe5346a32245727de5483739..8084baaa70d393150daa12d204250806168bfabc 100644
--- a/example/brunel/brunel.cpp
+++ b/example/brunel/brunel.cpp
@@ -119,12 +119,12 @@ public:
         std::vector<cell_connection> connections;
         // Add incoming excitatory connections.
         for (auto i: sample_subset(gid, 0, ncells_exc_, in_degree_exc_)) {
-            connections.push_back({{cell_gid_type(i), 0}, {gid, 0}, weight_exc_, delay_});
+            connections.push_back({{cell_gid_type(i), 0}, 0, weight_exc_, delay_});
         }
 
         // Add incoming inhibitory connections.
         for (auto i: sample_subset(gid, ncells_exc_, ncells_exc_ + ncells_inh_, in_degree_inh_)) {
-            connections.push_back({{cell_gid_type(i), 0}, {gid, 0}, weight_inh_, delay_});
+            connections.push_back({{cell_gid_type(i), 0}, 0, weight_inh_, delay_});
         }
         return connections;
     }
@@ -145,7 +145,7 @@ public:
         std::mt19937_64 G;
         G.seed(gid + seed_);
         time_type t0 = 0;
-        return {poisson_generator({gid, 0}, weight_ext_, t0, lambda_, G)};
+        return {poisson_generator(0, weight_ext_, t0, lambda_, G)};
     }
 
     cell_size_type num_sources(cell_gid_type) const override {
diff --git a/example/dryrun/dryrun.cpp b/example/dryrun/dryrun.cpp
index 458938e7c0d7f0784a4febf7dfbd7dacea87d0ed..a743ac753983a5dcff0aa913fd886b5ac2419f73 100644
--- a/example/dryrun/dryrun.cpp
+++ b/example/dryrun/dryrun.cpp
@@ -108,7 +108,7 @@ public:
         auto src = source_distribution(src_gen);
         if (src>=gid) ++src;
 
-        return {arb::cell_connection({src, 0}, {gid, 0}, event_weight_, min_delay_)};
+        return {arb::cell_connection({src, 0}, 0, event_weight_, min_delay_)};
     }
 
     // Return an event generator on every 20th gid. This function needs to generate events
@@ -117,7 +117,7 @@ public:
     std::vector<arb::event_generator> event_generators(cell_gid_type gid) const override {
         std::vector<arb::event_generator> gens;
         if (gid%20 == 0) {
-            gens.push_back(arb::explicit_generator(arb::pse_vector{{{gid, 0}, 1.0, event_weight_}}));
+            gens.push_back(arb::explicit_generator(arb::pse_vector{{0, 1.0, event_weight_}}));
         }
         return gens;
     }
diff --git a/example/gap_junctions/gap_junctions.cpp b/example/gap_junctions/gap_junctions.cpp
index 323d7667bac3b96d864d63e4ed21375bb1e2f0ec..4c16d2bcb95665d0aec2a41ea528c28753d41a2d 100644
--- a/example/gap_junctions/gap_junctions.cpp
+++ b/example/gap_junctions/gap_junctions.cpp
@@ -91,7 +91,7 @@ public:
         if(gid % params_.n_cells_per_cable || (int)gid - 1 < 0) {
             return{};
         }
-        return {arb::cell_connection({gid - 1, 0}, {gid, 0}, params_.event_weight, params_.event_min_delay)};
+        return {arb::cell_connection({gid - 1, 0}, 0, params_.event_weight, params_.event_min_delay)};
     }
 
     std::vector<arb::probe_info> get_probes(cell_gid_type gid) const override {
@@ -121,10 +121,10 @@ public:
         // Gap junction conductance in μS
 
         if (next_cell < cable_end) {
-            conns.push_back(arb::gap_junction_connection({(cell_gid_type)next_cell, 0}, {gid, 1}, 0.015));
+            conns.push_back(arb::gap_junction_connection({(cell_gid_type)next_cell, 0}, 1, 0.015));
         }
         if (prev_cell >= cable_begin) {
-            conns.push_back(arb::gap_junction_connection({(cell_gid_type)prev_cell, 1}, {gid, 0}, 0.015));
+            conns.push_back(arb::gap_junction_connection({(cell_gid_type)prev_cell, 1}, 0, 0.015));
         }
 
         return conns;
diff --git a/example/generators/generators.cpp b/example/generators/generators.cpp
index 5b62c95f25e4e763deef3fc91a3fabddeecf2722..a2747ea3850ac5d4623c2f41d09080e0240a1686 100644
--- a/example/generators/generators.cpp
+++ b/example/generators/generators.cpp
@@ -103,15 +103,15 @@ public:
 
         // Add excitatory generator
         gens.push_back(
-            poisson_generator(cell_member_type{0,0}, // Target synapse (gid, local_id).
-                              w_e,                   // Weight of events to deliver
-                              t0,                    // Events start being delivered from this time
-                              lambda_e,              // Expected frequency (kHz)
-                              RNG(29562872)));       // Random number generator to use
+            arb::poisson_generator(0,              // Target synapse index on cell `gid`
+                                   w_e,                   // Weight of events to deliver
+                                   t0,                    // Events start being delivered from this time
+                                   lambda_e,              // Expected frequency (kHz)
+                                   RNG(29562872)));       // Random number generator to use
 
         // Add inhibitory generator
         gens.emplace_back(
-            poisson_generator(cell_member_type{0,0}, w_i, t0, lambda_i,  RNG(86543891)));
+            arb::poisson_generator(0, w_i, t0, lambda_i,  RNG(86543891)));
 
         return gens;
     }
diff --git a/example/lfp/lfp.cpp b/example/lfp/lfp.cpp
index 29a557d822b52cfe14e4947fc11aa72e55683ba5..10c463ad2c2410988ed001c54eb62ac3da092acb 100644
--- a/example/lfp/lfp.cpp
+++ b/example/lfp/lfp.cpp
@@ -187,7 +187,7 @@ int main(int argc, char** argv) {
     auto context = arb::make_context();
 
     // Weight 0.005 μS, onset at t = 0 ms, mean frequency 0.1 kHz.
-    auto events = arb::poisson_generator({0, 0}, .005, 0., 0.1, std::minstd_rand{});
+    auto events = arb::poisson_generator(0, .005, 0., 0.1, std::minstd_rand{});
     lfp_demo_recipe R(events);
 
     const double t_stop = 100;    // [ms]
diff --git a/example/ring/ring.cpp b/example/ring/ring.cpp
index a6bfbd1e1ebba37347daf1826b7b635a5b349259..c3091d5a8670a8d08a048a1d742c63e2ed216a21 100644
--- a/example/ring/ring.cpp
+++ b/example/ring/ring.cpp
@@ -97,7 +97,7 @@ public:
     // Each cell has one incoming connection, from cell with gid-1.
     std::vector<arb::cell_connection> connections_on(cell_gid_type gid) const override {
         cell_gid_type src = gid? gid-1: num_cells_-1;
-        return {arb::cell_connection({src, 0}, {gid, 0}, event_weight_, min_delay_)};
+        return {arb::cell_connection({src, 0}, 0, event_weight_, min_delay_)};
     }
 
     // Return one event generator on gid 0. This generates a single event that will
@@ -105,7 +105,7 @@ public:
     std::vector<arb::event_generator> event_generators(cell_gid_type gid) const override {
         std::vector<arb::event_generator> gens;
         if (!gid) {
-            gens.push_back(arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, event_weight_}}));
+            gens.push_back(arb::explicit_generator(arb::pse_vector{{0, 1.0, event_weight_}}));
         }
         return gens;
     }
diff --git a/example/single/single.cpp b/example/single/single.cpp
index b3be1a02aa126e3fe6beb08456d8e055f8bdcd3f..bbe7fcbe43e1e52ee6315ddba76c38e1fb6b068a 100644
--- a/example/single/single.cpp
+++ b/example/single/single.cpp
@@ -97,8 +97,9 @@ int main(int argc, char** argv) {
         // Trigger the single synapse (target is gid 0, index 0) at t = 1 ms with
         // the given weight.
 
-        arb::spike_event spike = {{0, 0}, 1., opt.syn_weight};
-        sim.inject_events({spike});
+        arb::spike_event spike = {0, 1., opt.syn_weight};
+        arb::cell_spike_events cell_spikes = {0, {spike}};
+        sim.inject_events({cell_spikes});
 
         sim.run(opt.t_end, opt.dt);
 
diff --git a/python/event_generator.cpp b/python/event_generator.cpp
index f89df17c1f2c9700a4c4a01d59f1b28ab019ad42..ad7d0bbd27d4772200aa6a866241bfd65e91f0fe 100644
--- a/python/event_generator.cpp
+++ b/python/event_generator.cpp
@@ -17,7 +17,7 @@ void register_event_generators(pybind11::module& m) {
 
     event_generator
         .def(pybind11::init<>(
-            [](arb::cell_member_type target, double weight, const schedule_shim_base& sched) {
+            [](arb::cell_lid_type target, double weight, const schedule_shim_base& sched) {
                 return event_generator_shim(target, weight, sched.schedule()); }),
             "target"_a, "weight"_a, "sched"_a,
             "Construct an event generator with arguments:\n"
diff --git a/python/event_generator.hpp b/python/event_generator.hpp
index d58d8d4d65ad2234005dc1932849edd8dfac9dca..1d0d61c3ac50dea1499ef6f981e959d32b4b1534 100644
--- a/python/event_generator.hpp
+++ b/python/event_generator.hpp
@@ -6,12 +6,12 @@
 namespace pyarb {
 
 struct event_generator_shim {
-    arb::cell_member_type target;
+    arb::cell_lid_type target;
     double weight;
     arb::schedule time_sched;
 
-    event_generator_shim(arb::cell_member_type gid, double event_weight, arb::schedule sched):
-        target(gid),
+    event_generator_shim(arb::cell_lid_type event_target, double event_weight, arb::schedule sched):
+        target(event_target),
         weight(event_weight),
         time_sched(std::move(sched))
     {}
diff --git a/python/example/brunel.py b/python/example/brunel.py
index d1081fc347778c3a0fb4140585aae49857d24c71..3bd0af9e470e8ae3032686332ce330a941ba5f97 100755
--- a/python/example/brunel.py
+++ b/python/example/brunel.py
@@ -64,10 +64,10 @@ class brunel_recipe (arbor.recipe):
         connections=[]
         # Add incoming excitatory connections.
         for i in sample_subset(gid, 0, self.ncells_exc_, self.in_degree_exc_):
-            connections.append(arbor.connection((i,0), (gid,0), self.weight_exc_, self.delay_))
+            connections.append(arbor.connection((i,0), 0, self.weight_exc_, self.delay_))
         # Add incoming inhibitory connections.
         for i in sample_subset(gid, self.ncells_exc_, self.ncells_exc_ + self.ncells_inh_, self.in_degree_inh_):
-            connections.append(arbor.connection((i,0), (gid,0), self.weight_inh_, self.delay_))
+            connections.append(arbor.connection((i,0), 0, self.weight_inh_, self.delay_))
         return connections
 
     def cell_description(self, gid):
@@ -83,8 +83,9 @@ class brunel_recipe (arbor.recipe):
 
     def event_generators(self, gid):
         t0 = 0
+        idx = 0
         sched = arbor.poisson_schedule(t0, self.lambda_, gid + self.seed_)
-        return [arbor.event_generator(arbor.cell_member(gid,0), self.weight_ext_, sched)]
+        return [arbor.event_generator(idx, self.weight_ext_, sched)]
 
     def num_targets(self, gid):
         return 1
diff --git a/python/example/network_ring.py b/python/example/network_ring.py
index 14671b3b362c0b7c4f179710db4d11234a598b29..236570658edea5b6aa288ccb2fa653ef2f76b6f5 100755
--- a/python/example/network_ring.py
+++ b/python/example/network_ring.py
@@ -88,7 +88,7 @@ class ring_recipe (arbor.recipe):
         src = (gid-1)%self.ncells
         w = 0.01
         d = 5
-        return [arbor.connection((src,0), (gid,0), w, d)]
+        return [arbor.connection((src,0), 0, w, d)]
 
     def num_targets(self, gid):
         return 1
@@ -100,7 +100,7 @@ class ring_recipe (arbor.recipe):
     def event_generators(self, gid):
         if gid==0:
             sched = arbor.explicit_schedule([1])
-            return [arbor.event_generator((0,0), 0.1, sched)]
+            return [arbor.event_generator(0, 0.1, sched)]
         return []
 
     # (10) Place a probe at the root of each cell.
diff --git a/python/example/single_cell_stdp.py b/python/example/single_cell_stdp.py
index 84fa6550fa2e02acc721717f129a3845fb69a714..2c783520e31034888c499437560114677a391f55 100755
--- a/python/example/single_cell_stdp.py
+++ b/python/example/single_cell_stdp.py
@@ -59,12 +59,10 @@ class single_recipe(arbor.recipe):
         stimulus_times = numpy.linspace(50, 500, self.n_pairs)
 
         # strong enough stimulus
-        spike = arbor.event_generator(arbor.cell_member(
-            0, 0), 1., arbor.explicit_schedule(stimulus_times))
+        spike = arbor.event_generator(0, 1., arbor.explicit_schedule(stimulus_times))
 
         # zero weight -> just modify synaptic weight via stdp
-        stdp = arbor.event_generator(arbor.cell_member(
-            0, 1), 0., arbor.explicit_schedule(stimulus_times - self.dT))
+        stdp = arbor.event_generator(1, 0., arbor.explicit_schedule(stimulus_times - self.dT))
 
         return [spike, stdp]
 
diff --git a/python/recipe.cpp b/python/recipe.cpp
index 21b9a7ec44b4723c1a4f9936d7ca64007c83c001..9456dd3d407bdc62c5a826fc35d7340c6ee1a68c 100644
--- a/python/recipe.cpp
+++ b/python/recipe.cpp
@@ -103,7 +103,7 @@ static std::vector<arb::event_generator> convert_gen(std::vector<pybind11::objec
         auto& p = cast<const pyarb::event_generator_shim&>(g);
 
         // convert the event_generator to an arb::event_generator
-        gens.push_back(arb::schedule_generator({gid, p.target.index}, p.weight, std::move(p.time_sched)));
+        gens.push_back(arb::schedule_generator(p.target, p.weight, std::move(p.time_sched)));
     }
 
     return gens;
@@ -118,13 +118,13 @@ std::vector<arb::event_generator> py_recipe_shim::event_generators(arb::cell_gid
 }
 
 std::string con_to_string(const arb::cell_connection& c) {
-    return util::pprintf("<arbor.connection: source ({},{}), destination ({},{}), delay {}, weight {}>",
-         c.source.gid, c.source.index, c.dest.gid, c.dest.index, c.delay, c.weight);
+    return util::pprintf("<arbor.connection: source ({},{}), destination {}, delay {}, weight {}>",
+         c.source.gid, c.source.index, c.dest, c.delay, c.weight);
 }
 
 std::string gj_to_string(const arb::gap_junction_connection& gc) {
-    return util::pprintf("<arbor.gap_junction_connection: local ({},{}), peer ({},{}), ggap {}>",
-         gc.local.gid, gc.local.index, gc.peer.gid, gc.peer.index, gc.ggap);
+    return util::pprintf("<arbor.gap_junction_connection: peer ({},{}), local {}, ggap {}>",
+         gc.peer.gid, gc.peer.index, gc.local, gc.ggap);
 }
 
 void register_recipe(pybind11::module& m) {
@@ -135,7 +135,7 @@ void register_recipe(pybind11::module& m) {
         "Describes a connection between two cells:\n"
         "  Defined by source and destination end points (that is pre-synaptic and post-synaptic respectively), a connection weight and a delay time.");
     cell_connection
-        .def(pybind11::init<arb::cell_member_type, arb::cell_member_type, float, float>(),
+        .def(pybind11::init<arb::cell_member_type, arb::cell_lid_type, float, float>(),
             "source"_a, "dest"_a, "weight"_a, "delay"_a,
             "Construct a connection with arguments:\n"
             "  source:      The source end point of the connection.\n"
@@ -157,7 +157,7 @@ void register_recipe(pybind11::module& m) {
     pybind11::class_<arb::gap_junction_connection> gap_junction_connection(m, "gap_junction_connection",
         "Describes a gap junction between two gap junction sites.");
     gap_junction_connection
-        .def(pybind11::init<arb::cell_member_type, arb::cell_member_type, double>(),
+        .def(pybind11::init<arb::cell_member_type, arb::cell_lid_type, double>(),
             "local"_a, "peer"_a, "ggap"_a,
             "Construct a gap junction connection with arguments:\n"
             "  local: One half of the gap junction connection.\n"
diff --git a/test/unit-distributed/test_communicator.cpp b/test/unit-distributed/test_communicator.cpp
index 16c3527de7f5c2be2135c454cdf20f4cdbb75281..5c1f904a8a6b1fe3c221c7622def90401ee1968a 100644
--- a/test/unit-distributed/test_communicator.cpp
+++ b/test/unit-distributed/test_communicator.cpp
@@ -209,7 +209,7 @@ namespace {
             // weight is the destination gid
             // delay is 1
             cell_member_type src = {gid==0? size_-1: gid-1, 0};
-            cell_member_type dst = {gid, 0};
+            cell_lid_type dst = 0;
             return {cell_connection(
                         src, dst,   // end points
                         float(gid), // weight
@@ -233,7 +233,7 @@ namespace {
     spike_event expected_event_ring(cell_gid_type gid, cell_size_type num_cells) {
         auto sid = source_of(gid, num_cells);
         return {
-            {gid, 0u},  // source
+            0u,         // source
             sid+1.0f,   // time (all conns have delay 1 ms)
             float(gid)};// weight
     }
@@ -272,7 +272,7 @@ namespace {
             for (auto sid: util::make_span(0, size_)) {
                 cell_connection con(
                         {sid, 0},       // source
-                        {gid, sid},     // destination
+                        sid,     // destination
                         float(gid+sid), // weight
                         1.0f);          // delay
                 cons.push_back(con);
@@ -287,7 +287,7 @@ namespace {
 
     spike_event expected_event_all2all(cell_gid_type gid, cell_gid_type sid) {
         return {
-            {gid, sid},      // target, event from sid goes to synapse with index sid
+            sid,      // target, event from sid goes to synapse with index sid
             sid+1.0f,        // time (all conns have delay 1 ms)
             float(gid+sid)}; // weight
     }
diff --git a/test/unit-distributed/test_domain_decomposition.cpp b/test/unit-distributed/test_domain_decomposition.cpp
index 3b5c336cc7833c5d8822977b21ee00e64624bf26..e905f5645da48db7745b21a3a517721ea40df6cb 100644
--- a/test/unit-distributed/test_domain_decomposition.cpp
+++ b/test/unit-distributed/test_domain_decomposition.cpp
@@ -85,20 +85,20 @@ namespace {
         std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override {
             unsigned shift = (gid/size_)*size_;
             switch (gid % size_) {
-                case 1 :  return { gap_junction_connection({7 + shift, 0}, {gid, 0}, 0.1)};
+                case 1 :  return { gap_junction_connection({7 + shift, 0}, 0, 0.1)};
                 case 2 :  return {
-                    gap_junction_connection({6 + shift, 0}, {gid, 0}, 0.1),
-                    gap_junction_connection({9 + shift, 0}, {gid, 0}, 0.1)
+                    gap_junction_connection({6 + shift, 0}, 0, 0.1),
+                    gap_junction_connection({9 + shift, 0}, 0, 0.1)
                 };
                 case 6 :  return {
-                    gap_junction_connection({2 + shift, 0}, {gid, 0}, 0.1),
-                    gap_junction_connection({7 + shift, 0}, {gid, 0}, 0.1)
+                    gap_junction_connection({2 + shift, 0}, 0, 0.1),
+                    gap_junction_connection({7 + shift, 0}, 0, 0.1)
                 };
                 case 7 :  return {
-                    gap_junction_connection({6 + shift, 0}, {gid, 0}, 0.1),
-                    gap_junction_connection({1 + shift, 0}, {gid, 0}, 0.1)
+                    gap_junction_connection({6 + shift, 0}, 0, 0.1),
+                    gap_junction_connection({1 + shift, 0}, 0, 0.1)
                 };
-                case 9 :  return { gap_junction_connection({2 + shift, 0}, {gid, 0}, 0.1)};
+                case 9 :  return { gap_junction_connection({2 + shift, 0}, 0, 0.1)};
                 default : return {};
             }
         }
@@ -127,10 +127,10 @@ namespace {
             unsigned group = gid/groups_;
             unsigned id = gid%size_;
             if (id == group && group != (groups_ - 1)) {
-                return {gap_junction_connection({gid + size_, 0}, {gid, 0}, 0.1)};
+                return {gap_junction_connection({gid + size_, 0}, 0, 0.1)};
             }
             else if (id == group - 1) {
-                return {gap_junction_connection({gid - size_, 0}, {gid, 0}, 0.1)};
+                return {gap_junction_connection({gid - size_, 0}, 0, 0.1)};
             }
             else {
                 return {};
diff --git a/test/unit/test_domain_decomposition.cpp b/test/unit/test_domain_decomposition.cpp
index 8d7e97506722f07a93be786233bd210f24834d31..2db3367993446af5375cfc57a11d5764efca2695 100644
--- a/test/unit/test_domain_decomposition.cpp
+++ b/test/unit/test_domain_decomposition.cpp
@@ -77,34 +77,40 @@ namespace {
         }
         std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override {
             switch (gid) {
-                case 0 :  return {gap_junction_connection({13, 0}, {0, 0}, 0.1)};
+                case 0 :  return {
+                    gap_junction_connection({13, 0}, 0, 0.1)
+                };
                 case 2 :  return {
-                    gap_junction_connection({7, 0}, {2, 0}, 0.1),
-                    gap_junction_connection({11, 0}, {2, 0}, 0.1)
+                    gap_junction_connection({7, 0}, 0, 0.1),
+                    gap_junction_connection({11, 0}, 0, 0.1)
                 };
                 case 3 :  return {
-                    gap_junction_connection({4, 0}, {3, 0}, 0.1),
-                    gap_junction_connection({8, 0}, {3, 0}, 0.1)
+                    gap_junction_connection({4, 0}, 0, 0.1),
+                    gap_junction_connection({8, 0}, 0, 0.1)
                 };
                 case 4 :  return {
-                    gap_junction_connection({3, 0}, {4, 0}, 0.1),
-                    gap_junction_connection({8, 0}, {4, 0}, 0.1),
-                    gap_junction_connection({9, 0}, {4, 0}, 0.1)
+                    gap_junction_connection({3, 0}, 0, 0.1),
+                    gap_junction_connection({8, 0}, 0, 0.1),
+                    gap_junction_connection({9, 0}, 0, 0.1)
                 };
                 case 7 :  return {
-                    gap_junction_connection({2, 0}, {7, 0}, 0.1),
-                    gap_junction_connection({11, 0}, {7, 0}, 0.1)
+                    gap_junction_connection({2, 0}, 0, 0.1),
+                    gap_junction_connection({11, 0}, 0, 0.1)
                 };;
                 case 8 :  return {
-                    gap_junction_connection({3, 0}, {8, 0}, 0.1),
-                    gap_junction_connection({4, 0}, {8, 0}, 0.1)
+                    gap_junction_connection({3, 0}, 0, 0.1),
+                    gap_junction_connection({4, 0}, 0, 0.1)
                 };;
-                case 9 :  return {gap_junction_connection({4, 0}, {9, 0}, 0.1)};
+                case 9 :  return {
+                    gap_junction_connection({4, 0}, 0, 0.1)
+                };
                 case 11 : return {
-                    gap_junction_connection({2, 0}, {11, 0}, 0.1),
-                    gap_junction_connection({7, 0}, {11, 0}, 0.1)
+                    gap_junction_connection({2, 0}, 0, 0.1),
+                    gap_junction_connection({7, 0}, 0, 0.1)
+                };
+                case 13 : return {
+                    gap_junction_connection({0, 0}, 0, 0.1)
                 };
-                case 13 : return {gap_junction_connection({0, 0}, {13, 0}, 0.1)};
                 default : return {};
             }
         }
diff --git a/test/unit/test_event_delivery.cpp b/test/unit/test_event_delivery.cpp
index f8fa888e2dd224178a80059be637f4213e92a65b..1d4f9cd95c163e3cebb9b3092481b74aa8aa5556 100644
--- a/test/unit/test_event_delivery.cpp
+++ b/test/unit/test_event_delivery.cpp
@@ -75,9 +75,9 @@ std::vector<cell_gid_type> run_test_sim(const recipe& R, const group_gids_type&
 
     constexpr time_type ev_delta_t = 0.2;
 
-    pse_vector cell_events;
+    cse_vector cell_events;
     for (unsigned i = 0; i<n; ++i) {
-        cell_events.push_back({{i, 0u}, i*ev_delta_t, 1.f});
+        cell_events.push_back({i, {{0u, i*ev_delta_t, 1.f}}});
     }
 
     sim.inject_events(cell_events);
@@ -112,7 +112,8 @@ struct test_recipe_gj: public test_recipe {
     std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type i) const override {
         std::vector<gap_junction_connection> gjs;
         for (auto p: gj_pairs_) {
-            if (p.first == i || p.second == i) gjs.push_back({{p.first, 0u}, {p.second, 0u}, 0.});
+            if (p.first == i) gjs.push_back({{p.second, 0u}, 0u, 0.});
+            if (p.second == i) gjs.push_back({{p.first, 0u}, 0u, 0.});
         }
         return gjs;
     }
diff --git a/test/unit/test_event_generators.cpp b/test/unit/test_event_generators.cpp
index 032abda3d88aa9b0795447b1e8e770b74ae9a733..0f17feb47434835ae274689526a789257e7824d4 100644
--- a/test/unit/test_event_generators.cpp
+++ b/test/unit/test_event_generators.cpp
@@ -18,8 +18,8 @@ namespace{
 }
 
 TEST(event_generators, assign_and_copy) {
-    event_generator gen = regular_generator({1, 2}, 5., 0.5, 0.75);
-    spike_event expected{{1, 2}, 0.75, 5.};
+    event_generator gen = regular_generator(2, 5., 0.5, 0.75);
+    spike_event expected{2, 0.75, 5.};
 
     auto first = [](const event_seq& seq) {
         if (seq.first==seq.second) throw std::runtime_error("no events");
@@ -54,7 +54,7 @@ TEST(event_generators, regular) {
     // events regularly spaced 0.5 ms apart.
     time_type t0 = 2.0;
     time_type dt = 0.5;
-    cell_member_type target = {42, 3};
+    cell_lid_type target = 3;
     float weight = 3.14;
 
     event_generator gen = regular_generator(target, weight, t0, dt);
@@ -81,13 +81,13 @@ TEST(event_generators, regular) {
 
 TEST(event_generators, seq) {
     pse_vector in = {
-        {{0, 0}, 0.1, 1.0},
-        {{0, 0}, 1.0, 2.0},
-        {{0, 0}, 1.0, 3.0},
-        {{0, 0}, 1.5, 4.0},
-        {{0, 0}, 2.3, 5.0},
-        {{0, 0}, 3.0, 6.0},
-        {{0, 0}, 3.5, 7.0},
+        {0, 0.1, 1.0},
+        {0, 1.0, 2.0},
+        {0, 1.0, 3.0},
+        {0, 1.5, 4.0},
+        {0, 2.3, 5.0},
+        {0, 3.0, 6.0},
+        {0, 3.5, 7.0},
     };
 
     auto events = [&in] (int b, int e) {
@@ -102,10 +102,10 @@ TEST(event_generators, seq) {
 
     // Check reported sub-intervals against a smaller set of events.
     in = {
-        {{0, 0}, 1.5, 4.0},
-        {{0, 0}, 2.3, 5.0},
-        {{0, 0}, 3.0, 6.0},
-        {{0, 0}, 3.5, 7.0},
+        {0, 1.5, 4.0},
+        {0, 2.3, 5.0},
+        {0, 3.0, 6.0},
+        {0, 3.5, 7.0},
     };
     gen = explicit_generator(in);
 
@@ -143,7 +143,7 @@ TEST(event_generators, poisson) {
     time_type t0 = 0;
     time_type t1 = 10;
     time_type lambda = 10; // expect 10 events per ms
-    cell_member_type target{4, 2};
+    cell_lid_type target = 2;
     float weight = 42;
 
     event_generator gen = poisson_generator(target, weight, t0, lambda, G);
diff --git a/test/unit/test_event_queue.cpp b/test/unit/test_event_queue.cpp
index 3ce72e0bd7ddbe426619db582413867ebfde578d..b47a3ed32e0f980f21a56fe79701acce5d9b9a40 100644
--- a/test/unit/test_event_queue.cpp
+++ b/test/unit/test_event_queue.cpp
@@ -14,10 +14,10 @@ TEST(event_queue, push) {
 
     ps_event_queue q;
 
-    q.push({{1u, 0u}, 2.f, 2.f});
-    q.push({{4u, 1u}, 1.f, 2.f});
-    q.push({{8u, 2u}, 20.f, 2.f});
-    q.push({{2u, 3u}, 8.f, 2.f});
+    q.push({0u, 2.f, 2.f});
+    q.push({1u, 1.f, 2.f});
+    q.push({2u, 20.f, 2.f});
+    q.push({3u, 8.f, 2.f});
 
     EXPECT_EQ(4u, q.size());
 
@@ -33,12 +33,7 @@ TEST(event_queue, push) {
 TEST(event_queue, pop_if_before) {
     using ps_event_queue = event_queue<spike_event>;
 
-    cell_member_type target[4] = {
-        {1u, 0u},
-        {4u, 1u},
-        {8u, 2u},
-        {2u, 3u}
-    };
+    cell_lid_type target[4] = {0u, 1u, 2u, 3u};
 
     spike_event events[] = {
         {target[0], 1.f, 2.f},
diff --git a/test/unit/test_fvm_lowered.cpp b/test/unit/test_fvm_lowered.cpp
index 5d11cff324a497ea27a99cfd47a81350eda2e1c1..a35e83931b662fece9be1a10e1573a35459336d7 100644
--- a/test/unit/test_fvm_lowered.cpp
+++ b/test/unit/test_fvm_lowered.cpp
@@ -107,21 +107,21 @@ public:
     std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override {
         switch (gid) {
             case 0 :
-                return {gap_junction_connection({5, 0}, {0, 0}, 0.1)};
+                return {gap_junction_connection({5, 0}, 0, 0.1)};
             case 2 :
                 return {
-                        gap_junction_connection({3, 0}, {2, 0}, 0.1),
+                        gap_junction_connection({3, 0}, 0, 0.1),
                 };
             case 3 :
                 return {
-                        gap_junction_connection({7, 0}, {3, 0}, 0.1),
-                        gap_junction_connection({3, 0}, {2, 0}, 0.1)
+                        gap_junction_connection({7, 0}, 0, 0.1),
+                        gap_junction_connection({2, 0}, 0, 0.1)
                 };
             case 5 :
-                return {gap_junction_connection({5, 0}, {0, 0}, 0.1)};
+                return {gap_junction_connection({0, 0}, 0, 0.1)};
             case 7 :
                 return {
-                        gap_junction_connection({3, 0}, {7, 0}, 0.1),
+                        gap_junction_connection({3, 0}, 0, 0.1),
                 };
             default :
                 return {};
@@ -173,27 +173,27 @@ public:
         switch (gid) {
             case 0 :
                 return {
-                        gap_junction_connection({2, 0}, {0, 0}, 0.1),
-                        gap_junction_connection({3, 0}, {0, 0}, 0.1),
-                        gap_junction_connection({5, 0}, {0, 0}, 0.1)
+                        gap_junction_connection({2, 0}, 0, 0.1),
+                        gap_junction_connection({3, 0}, 0, 0.1),
+                        gap_junction_connection({5, 0}, 0, 0.1)
                 };
             case 2 :
                 return {
-                        gap_junction_connection({0, 0}, {2, 0}, 0.1),
-                        gap_junction_connection({3, 0}, {2, 0}, 0.1),
-                        gap_junction_connection({5, 0}, {2, 0}, 0.1)
+                        gap_junction_connection({0, 0}, 0, 0.1),
+                        gap_junction_connection({3, 0}, 0, 0.1),
+                        gap_junction_connection({5, 0}, 0, 0.1)
                 };
             case 3 :
                 return {
-                        gap_junction_connection({0, 0}, {3, 0}, 0.1),
-                        gap_junction_connection({2, 0}, {3, 0}, 0.1),
-                        gap_junction_connection({5, 0}, {3, 0}, 0.1)
+                        gap_junction_connection({0, 0}, 0, 0.1),
+                        gap_junction_connection({2, 0}, 0, 0.1),
+                        gap_junction_connection({5, 0}, 0, 0.1)
                 };
             case 5 :
                 return {
-                        gap_junction_connection({2, 0}, {5, 0}, 0.1),
-                        gap_junction_connection({3, 0}, {5, 0}, 0.1),
-                        gap_junction_connection({0, 0}, {5, 0}, 0.1)
+                        gap_junction_connection({2, 0}, 0, 0.1),
+                        gap_junction_connection({3, 0}, 0, 0.1),
+                        gap_junction_connection({0, 0}, 0, 0.1)
                 };
             default :
                 return {};
@@ -939,7 +939,7 @@ TEST(fvm_lowered, gj_coords_simple) {
         }
         std::vector<arb::gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override{
             std::vector<gap_junction_connection> conns;
-            conns.push_back(gap_junction_connection({(gid+1)%2, 0}, {gid, 0}, 0.5));
+            conns.push_back(gap_junction_connection({(gid+1)%2, 0}, 0, 0.5));
             return conns;
         }
 
@@ -1007,22 +1007,22 @@ TEST(fvm_lowered, gj_coords_complex) {
             switch (gid) {
             case 0:
                 return {
-                    gap_junction_connection({2, 0}, {0, 1}, 0.01),
-                    gap_junction_connection({1, 0}, {0, 0}, 0.03),
-                    gap_junction_connection({1, 1}, {0, 0}, 0.04)
+                    gap_junction_connection({2, 0}, 1, 0.01),
+                    gap_junction_connection({1, 0}, 0, 0.03),
+                    gap_junction_connection({1, 1}, 0, 0.04)
                 };
             case 1:
                 return {
-                    gap_junction_connection({0, 0}, {1, 0}, 0.03),
-                    gap_junction_connection({0, 0}, {1, 1}, 0.04),
-                    gap_junction_connection({2, 1}, {1, 2}, 0.02),
-                    gap_junction_connection({2, 2}, {1, 3}, 0.01)
+                    gap_junction_connection({0, 0}, 0, 0.03),
+                    gap_junction_connection({0, 0}, 1, 0.04),
+                    gap_junction_connection({2, 1}, 2, 0.02),
+                    gap_junction_connection({2, 2}, 3, 0.01)
                 };
             case 2:
                 return {
-                    gap_junction_connection({0, 1}, {2, 0}, 0.01),
-                    gap_junction_connection({1, 2}, {2, 1}, 0.02),
-                    gap_junction_connection({1, 3}, {2, 2}, 0.01)
+                    gap_junction_connection({0, 1}, 0, 0.01),
+                    gap_junction_connection({1, 2}, 1, 0.02),
+                    gap_junction_connection({1, 3}, 2, 0.01)
                 };
             default : return {};
             }
@@ -1152,8 +1152,8 @@ TEST(fvm_lowered, cell_group_gj) {
                 // connect 5 of the first 10 cells in a ring; connect 5 of the second 10 cells in a ring
                 auto next_cell = gid == 8 ? 0 : (gid == 18 ? 10 : gid + 2);
                 auto prev_cell = gid == 0 ? 8 : (gid == 10 ? 18 : gid - 2);
-                conns.push_back(gap_junction_connection({next_cell, 0}, {gid, 0}, 0.03));
-                conns.push_back(gap_junction_connection({prev_cell, 0}, {gid, 0}, 0.03));
+                conns.push_back(gap_junction_connection({next_cell, 0}, 0, 0.03));
+                conns.push_back(gap_junction_connection({prev_cell, 0}, 0, 0.03));
             }
             return conns;
         }
diff --git a/test/unit/test_lif_cell_group.cpp b/test/unit/test_lif_cell_group.cpp
index 664f7d8876eb930a7337e4c5f430064cbbe00818..272245a140062851e4b3e2e5c7300d183a4df000 100644
--- a/test/unit/test_lif_cell_group.cpp
+++ b/test/unit/test_lif_cell_group.cpp
@@ -42,7 +42,7 @@ public:
         std::vector<cell_connection> connections;
         // gid-1 >= 0 since gid != 0
         cell_member_type source{(gid - 1) % n_lif_cells_, 0};
-        cell_member_type target{gid, 0};
+        cell_lid_type target{0};
         cell_connection conn(source, target, weight_, delay_);
         connections.push_back(conn);
 
@@ -50,7 +50,7 @@ public:
         // the connection from the last LIF cell as well
         if (gid == 1) {
             cell_member_type source{n_lif_cells_, 0};
-            cell_member_type target{gid, 0};
+            cell_lid_type target{0};
             cell_connection conn(source, target, weight_, delay_);
             connections.push_back(conn);
         }
@@ -101,7 +101,7 @@ public:
         }
         std::vector<cell_connection> connections;
         cell_member_type source{gid - 1, 0};
-        cell_member_type target{gid, 0};
+        cell_lid_type target{0};
         cell_connection conn(source, target, weight_, delay_);
         connections.push_back(conn);
 
@@ -177,18 +177,18 @@ TEST(lif_cell_group, spikes) {
     auto decomp = partition_load_balance(recipe, context);
     simulation sim(recipe, decomp, context);
 
-    std::vector<spike_event> events;
+    cse_vector events;
 
     // First event to trigger the spike (first neuron).
-    events.push_back({{0, 0}, 1, 1000});
+    events.push_back({0, {{0, 1, 1000}}});
 
     // This event happens inside the refractory period of the previous
     // event, thus, should be ignored (first neuron)
-    events.push_back({{0, 0}, 1.1, 1000});
+    events.push_back({0, {{0, 1.1, 1000}}});
 
     // This event happens long after the refractory period of the previous
     // event, should thus trigger new spike (first neuron).
-    events.push_back({{0, 0}, 50, 1000});
+    events.push_back({0, {{0, 50, 1000}}});
 
     sim.inject_events(events);
 
diff --git a/test/unit/test_merge_events.cpp b/test/unit/test_merge_events.cpp
index d1756f4ed9ccce3bf4593e44cd27b688e26aad2b..d61363f4e1d8d9c5c1cd1d1574163cd54f74a7cc 100644
--- a/test/unit/test_merge_events.cpp
+++ b/test/unit/test_merge_events.cpp
@@ -54,9 +54,9 @@ TEST(merge_events, empty)
 TEST(merge_events, no_overlap)
 {
     pse_vector lc = {
-        {{0, 0}, 1, 1},
-        {{0, 0}, 2, 1},
-        {{0, 0}, 3, 3},
+        {0, 1, 1},
+        {0, 2, 1},
+        {0, 3, 3},
     };
     // Check that the inputs satisfy the precondition that lc is sorted.
     EXPECT_TRUE(std::is_sorted(lc.begin(), lc.end()));
@@ -64,25 +64,25 @@ TEST(merge_events, no_overlap)
     // These events should be removed from lf by merge_events, and replaced
     // with events to be delivered after t=10
     pse_vector lf = {
-        {{0, 0}, 1, 1},
-        {{0, 0}, 2, 1},
-        {{0, 0}, 3, 3},
+        {0, 1, 1},
+        {0, 2, 1},
+        {0, 3, 3},
     };
 
     pse_vector events = {
-        {{0, 0}, 12, 1},
-        {{0, 0}, 11, 2},
-        {{8, 0}, 10, 4},
-        {{0, 0}, 11, 1},
+        {0, 12, 1},
+        {0, 11, 2},
+        {0, 10, 4},
+        {0, 11, 1},
     };
 
     merge_events(10, terminal_time, lc, events, empty_gens, lf);
 
     pse_vector expected = {
-        {{8, 0}, 10, 4},
-        {{0, 0}, 11, 1},
-        {{0, 0}, 11, 2},
-        {{0, 0}, 12, 1},
+        {0, 10, 4},
+        {0, 11, 1},
+        {0, 11, 2},
+        {0, 12, 1},
     };
 
     EXPECT_TRUE(std::is_sorted(lf.begin(), lf.end()));
@@ -95,11 +95,11 @@ TEST(merge_events, no_overlap)
 TEST(merge_events, overlap)
 {
     pse_vector lc = {
-        {{0, 0}, 1, 1},
-        {{0, 0}, 2, 1},
+        {0, 1, 1},
+        {0, 2, 1},
         // The current epoch ends at t=10, so all events from here down are expected in lf.
-        {{8, 0}, 10, 2},
-        {{0, 0}, 11, 3},
+        {0, 10, 2},
+        {0, 11, 3},
     };
     EXPECT_TRUE(std::is_sorted(lc.begin(), lc.end()));
 
@@ -107,23 +107,23 @@ TEST(merge_events, overlap)
 
     pse_vector events = {
         // events are in reverse order: they should be sorted in the output of merge_events.
-        {{0, 0}, 12, 1},
-        {{0, 0}, 11, 2},
-        {{0, 0}, 11, 1},
-        {{8, 0}, 10, 3},
-        {{7, 0}, 10, 8},
+        {0, 12, 1},
+        {0, 11, 2},
+        {0, 11, 1},
+        {1, 10, 3},
+        {0, 10, 8},
     };
 
     merge_events(10, terminal_time, lc, events, empty_gens, lf);
 
     pse_vector expected = {
-        {{7, 0}, 10, 8}, // from events
-        {{8, 0}, 10, 2}, // from lc
-        {{8, 0}, 10, 3}, // from events
-        {{0, 0}, 11, 1}, // from events
-        {{0, 0}, 11, 2}, // from events
-        {{0, 0}, 11, 3}, // from lc
-        {{0, 0}, 12, 1}, // from events
+        {0, 10, 2}, // from lc
+        {0, 10, 8}, // from events
+        {1, 10, 3}, // from events
+        {0, 11, 1}, // from events
+        {0, 11, 2}, // from events
+        {0, 11, 3}, // from lc
+        {0, 12, 1}, // from events
     };
 
     EXPECT_TRUE(std::is_sorted(lf.begin(), lf.end()));
@@ -137,42 +137,42 @@ TEST(merge_events, X)
     const time_type t1 = 20;
 
     pse_vector lc = {
-        {{0, 0}, 1, 1},
-        {{0, 0}, 5, 1},
+        {0, 1, 1},
+        {0, 5, 1},
         // The current epoch ends at t=10, so all events from here down are expected in lf.
-        {{8, 0}, 10, 2},
-        {{0, 0}, 11, 3},
-        {{8, 0}, 20, 2},
-        {{0, 0}, 21, 3},
+        {0, 10, 2},
+        {0, 11, 3},
+        {0, 20, 2},
+        {0, 21, 3},
     };
     EXPECT_TRUE(std::is_sorted(lc.begin(), lc.end()));
 
     pse_vector lf;
 
     pse_vector events = {
-        {{0, 0}, 12, 1},
-        {{1, 0}, 15, 2},
-        {{2, 0}, 22, 3},
-        {{3, 0}, 26, 4},
+        {0, 12, 1},
+        {0, 15, 2},
+        {0, 22, 3},
+        {0, 26, 4},
     };
 
     std::vector<event_generator> generators = {
-        regular_generator(cell_member_type{4,2}, 42.f, t0, 5)
+        regular_generator(2, 42.f, t0, 5)
     };
 
     merge_events(t0, t1, lc, events, generators, lf);
 
     pse_vector expected = {
-        {{4, 2}, 10, 42}, // from generator
-        {{8, 0}, 10, 2},  // from lc
-        {{0, 0}, 11, 3},  // from lc
-        {{0, 0}, 12, 1},  // from events
-        {{1, 0}, 15, 2},  // from events
-        {{4, 2}, 15, 42}, // from generator
-        {{8, 0}, 20, 2},  // from lc
-        {{0, 0}, 21, 3},  // from lc
-        {{2, 0}, 22, 3},  // from events
-        {{3, 0}, 26, 4},  // from events
+        {0, 10, 2},  // from lc
+        {2, 10, 42}, // from generator
+        {0, 11, 3},  // from lc
+        {0, 12, 1},  // from events
+        {0, 15, 2},  // from events
+        {2, 15, 42}, // from generator
+        {0, 20, 2},  // from lc
+        {0, 21, 3},  // from lc
+        {0, 22, 3},  // from events
+        {0, 26, 4},  // from events
     };
 
     EXPECT_TRUE(std::is_sorted(lf.begin(), lf.end()));
@@ -183,19 +183,19 @@ TEST(merge_events, X)
 TEST(merge_events, tourney_seq)
 {
     pse_vector evs1 = {
-        {{0, 0}, 1, 1},
-        {{0, 0}, 2, 2},
-        {{0, 0}, 3, 3},
-        {{0, 0}, 4, 4},
-        {{0, 0}, 5, 5},
+        {0, 1, 1},
+        {0, 2, 2},
+        {0, 3, 3},
+        {0, 4, 4},
+        {0, 5, 5},
     };
 
     pse_vector evs2 = {
-        {{0, 0}, 1.5, 1},
-        {{0, 0}, 2.5, 2},
-        {{0, 0}, 3.5, 3},
-        {{0, 0}, 4.5, 4},
-        {{0, 0}, 5.5, 5},
+        {0, 1.5, 1},
+        {0, 2.5, 2},
+        {0, 3.5, 3},
+        {0, 4.5, 4},
+        {0, 5.5, 5},
     };
 
     event_generator g1 = explicit_generator(evs1);
@@ -234,7 +234,7 @@ TEST(merge_events, tourney_poisson)
 
     std::vector<event_generator> generators;
     for (auto i=0u; i<ngen; ++i) {
-        cell_member_type tgt{0, i};
+        cell_lid_type tgt = i;
         float weight = i;
         // the first and last generators have the same seed to test that sorting
         // of events with the same time but different weights works properly.
diff --git a/test/unit/test_probe.cpp b/test/unit/test_probe.cpp
index f08a4cf0f34f3a6a82f421a1b2fc07e4944f6926..7e705019217bc3105854600730570937231724f5 100644
--- a/test/unit/test_probe.cpp
+++ b/test/unit/test_probe.cpp
@@ -1249,9 +1249,9 @@ void run_exact_sampling_probe_test(const context& ctx) {
         std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override {
             switch (gid) {
             case 1:
-                return {gap_junction_connection({gid, 0}, {3, 0}, 1.)};
+                return {gap_junction_connection({3, 0}, 0, 1.)};
             case 3:
-                return {gap_junction_connection({gid, 0}, {1, 0}, 1.)};
+                return {gap_junction_connection({1, 0}, 0, 1.)};
             default:
                 return {};
             }
@@ -1259,7 +1259,7 @@ void run_exact_sampling_probe_test(const context& ctx) {
 
         std::vector<event_generator> event_generators(cell_gid_type gid) const override {
             // Send a single event to cell i at 0.1*i milliseconds.
-            pse_vector spikes = {spike_event{{gid, 0}, 0.1*gid, 1.f}};
+            pse_vector spikes = {spike_event{0, 0.1*gid, 1.f}};
             return {explicit_generator(spikes)};
         }
 
diff --git a/test/unit/test_recipe.cpp b/test/unit/test_recipe.cpp
index 0d2a648985bf268c4dae50e707513224931b26a4..b1b0c04eea577e705b6bb9706d2e22656afa0abb 100644
--- a/test/unit/test_recipe.cpp
+++ b/test/unit/test_recipe.cpp
@@ -171,36 +171,34 @@ TEST(recipe, gap_junctions)
     auto cell_1 = custom_cell(0, 0, 3);
 
     {
-        std::vector<arb::gap_junction_connection> gjs_0 = {{{0, 0}, {1, 1}, 0.1},
-                                                           {{0, 1}, {1, 2}, 0.1},
-                                                           {{0, 2}, {1, 0}, 0.1}};
+        std::vector<arb::gap_junction_connection> gjs_0 = {{{1, 1}, 0, 0.1},
+                                                           {{1, 2}, 1, 0.1},
+                                                           {{1, 0}, 2, 0.1}};
 
-        auto recipe_0 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_0, gjs_0}, {{}, {}});
+        std::vector<arb::gap_junction_connection> gjs_1 = {{{0, 0}, 1, 0.1},
+                                                           {{0, 1}, 2, 0.1},
+                                                           {{0, 2}, 0, 0.1}};
+
+        auto recipe_0 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_0, gjs_1}, {{}, {}});
         auto decomp_0 = partition_load_balance(recipe_0, context);
 
         EXPECT_NO_THROW(simulation(recipe_0, decomp_0, context));
     }
     {
-        std::vector<arb::gap_junction_connection> gjs_1 = {{{0, 0}, {1, 1}, 0.1},
-                                                           {{0, 1}, {1, 2}, 0.1},
-                                                           {{0, 2}, {1, 5}, 0.1}};
+        std::vector<arb::gap_junction_connection> gjs_0 = {{{1, 1}, 0, 0.1},
+                                                           {{1, 2}, 1, 0.1},
+                                                           {{1, 5}, 2, 0.1}};
+
+        std::vector<arb::gap_junction_connection> gjs_1 = {{{0, 0}, 1, 0.1},
+                                                           {{0, 1}, 2, 0.1},
+                                                           {{0, 2}, 5, 0.1}};
 
-        auto recipe_1 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_1, gjs_1}, {{}, {}});
+        auto recipe_1 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_0, gjs_1}, {{}, {}});
         auto decomp_1 = partition_load_balance(recipe_1, context);
 
         EXPECT_THROW(simulation(recipe_1, decomp_1, context), arb::bad_gj_connection_lid);
 
     }
-    {
-        std::vector<arb::gap_junction_connection> gjs_2 = {{{0, 0}, {1, 1}, 0.1},
-                                                           {{0, 1}, {1, 2}, 0.1},
-                                                           {{0, 2}, {3, 0}, 0.1}};
-
-        auto recipe_2 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_2, gjs_2}, {{}, {}});
-        auto context = make_context(resources);
-
-        EXPECT_THROW(partition_load_balance(recipe_2, context), arb::bad_gj_connection_gid);
-    }
 }
 
 TEST(recipe, connections)
@@ -218,13 +216,13 @@ TEST(recipe, connections)
     auto cell_1 = custom_cell(2, 1, 0);
     std::vector<arb::cell_connection> conns_0, conns_1;
     {
-        conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1},
-                   {{1, 1}, {0, 0}, 0.1, 0.1},
-                   {{1, 0}, {0, 1}, 0.2, 0.4}};
+        conns_0 = {{{1, 0}, 0, 0.1, 0.1},
+                   {{1, 1}, 0, 0.1, 0.1},
+                   {{1, 0}, 1, 0.2, 0.4}};
 
-        conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2},
-                   {{0, 0}, {1, 0}, 0.3, 0.1},
-                   {{0, 0}, {1, 0}, 0.1, 0.8}};
+        conns_1 = {{{0, 0}, 0, 0.1, 0.2},
+                   {{0, 0}, 0, 0.3, 0.1},
+                   {{0, 0}, 0, 0.1, 0.8}};
 
         auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}},  {{}, {}});
         auto decomp_0 = partition_load_balance(recipe_0, context);
@@ -232,13 +230,13 @@ TEST(recipe, connections)
         EXPECT_NO_THROW(simulation(recipe_0, decomp_0, context));
     }
     {
-        conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1},
-                   {{2, 1}, {0, 0}, 0.1, 0.1},
-                   {{1, 0}, {0, 1}, 0.2, 0.4}};
+        conns_0 = {{{1, 0}, 0, 0.1, 0.1},
+                   {{2, 1}, 0, 0.1, 0.1},
+                   {{1, 0}, 1, 0.2, 0.4}};
 
-        conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2},
-                   {{0, 0}, {1, 0}, 0.3, 0.1},
-                   {{0, 0}, {1, 0}, 0.1, 0.8}};
+        conns_1 = {{{0, 0}, 0, 0.1, 0.2},
+                   {{0, 0}, 0, 0.3, 0.1},
+                   {{0, 0}, 0, 0.1, 0.8}};
 
         auto recipe_1 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}},  {{}, {}});
         auto decomp_1 = partition_load_balance(recipe_1, context);
@@ -246,13 +244,13 @@ TEST(recipe, connections)
         EXPECT_THROW(simulation(recipe_1, decomp_1, context), arb::bad_connection_source_gid);
     }
     {
-        conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1},
-                   {{1, 1}, {0, 0}, 0.1, 0.1},
-                   {{1, 3}, {0, 1}, 0.2, 0.4}};
+        conns_0 = {{{1, 0}, 0, 0.1, 0.1},
+                   {{1, 1}, 0, 0.1, 0.1},
+                   {{1, 3}, 1, 0.2, 0.4}};
 
-        conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2},
-                   {{0, 0}, {1, 0}, 0.3, 0.1},
-                   {{0, 0}, {1, 0}, 0.1, 0.8}};
+        conns_1 = {{{0, 0}, 0, 0.1, 0.2},
+                   {{0, 0}, 0, 0.3, 0.1},
+                   {{0, 0}, 0, 0.1, 0.8}};
 
         auto recipe_2 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}},  {{}, {}});
         auto decomp_2 = partition_load_balance(recipe_2, context);
@@ -260,41 +258,13 @@ TEST(recipe, connections)
         EXPECT_THROW(simulation(recipe_2, decomp_2, context), arb::bad_connection_source_lid);
     }
     {
-        conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1},
-                   {{1, 1}, {0, 0}, 0.1, 0.1},
-                   {{1, 0}, {0, 1}, 0.2, 0.4}};
-
-        conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2},
-                   {{0, 0}, {7, 0}, 0.3, 0.1},
-                   {{0, 0}, {1, 0}, 0.1, 0.8}};
-
-        auto recipe_3 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}},  {{}, {}});
-        auto decomp_3 = partition_load_balance(recipe_3, context);
-
-        EXPECT_THROW(simulation(recipe_3, decomp_3, context), arb::bad_connection_target_gid);
-    }
-    {
-        conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1},
-                   {{1, 1}, {0, 0}, 0.1, 0.1},
-                   {{1, 0}, {0, 1}, 0.2, 0.4}};
+        conns_0 = {{{1, 0}, 0, 0.1, 0.1},
+                   {{1, 1}, 0, 0.1, 0.1},
+                   {{1, 0}, 1, 0.2, 0.4}};
 
-        conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2},
-                   {{0, 0}, {0, 0}, 0.3, 0.1},
-                   {{0, 0}, {1, 0}, 0.1, 0.8}};
-
-        auto recipe_5 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}},  {{}, {}});
-        auto decomp_5 = partition_load_balance(recipe_5, context);
-
-        EXPECT_THROW(simulation(recipe_5, decomp_5, context), arb::bad_connection_target_gid);
-    }
-    {
-        conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1},
-                   {{1, 1}, {0, 0}, 0.1, 0.1},
-                   {{1, 0}, {0, 1}, 0.2, 0.4}};
-
-        conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2},
-                   {{0, 0}, {1, 9}, 0.3, 0.1},
-                   {{0, 0}, {1, 0}, 0.1, 0.8}};
+        conns_1 = {{{0, 0}, 0, 0.1, 0.2},
+                   {{0, 0}, 9, 0.3, 0.1},
+                   {{0, 0}, 0, 0.1, 0.8}};
 
         auto recipe_4 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}},  {{}, {}});
         auto decomp_4 = partition_load_balance(recipe_4, context);
@@ -317,9 +287,9 @@ TEST(recipe, event_generators) {
     auto cell_1 = custom_cell(2, 1, 0);
     std::vector<arb::event_generator> gens_0, gens_1;
     {
-        gens_0 = {arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, 0.1}, {{0, 1}, 2.0, 0.1}})};
+        gens_0 = {arb::explicit_generator(arb::pse_vector{{0, 1.0, 0.1}, {1, 2.0, 0.1}})};
 
-        gens_1 = {arb::explicit_generator(arb::pse_vector{{{1, 0}, 1.0, 0.1}})};
+        gens_1 = {arb::explicit_generator(arb::pse_vector{{0, 1.0, 0.1}})};
 
         auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {{}, {}}, {{}, {}},  {gens_0, gens_1});
         auto decomp_0 = partition_load_balance(recipe_0, context);
@@ -327,16 +297,7 @@ TEST(recipe, event_generators) {
         EXPECT_NO_THROW(simulation(recipe_0, decomp_0, context));
     }
     {
-        gens_0.clear();
-        gens_1 = {arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, 0.1}})};
-
-        auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {{}, {}}, {{}, {}},  {gens_0, gens_1});
-        auto decomp_0 = partition_load_balance(recipe_0, context);
-
-        EXPECT_THROW(simulation(recipe_0, decomp_0, context), arb::bad_event_generator_target_gid);
-    }
-    {
-        gens_0 = {arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, 0.1}, {{0, 3}, 2.0, 0.1}})};
+        gens_0 = {arb::explicit_generator(arb::pse_vector{{0, 1.0, 0.1}, {3, 2.0, 0.1}})};
         gens_1.clear();
 
         auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {{}, {}}, {{}, {}},  {gens_0, gens_1});
diff --git a/test/unit/test_simulation.cpp b/test/unit/test_simulation.cpp
index dda5be17163645f5815f5d05326836eddaa5c151..88d39b72b49717410a5ab71957188deb9fa92e0d 100644
--- a/test/unit/test_simulation.cpp
+++ b/test/unit/test_simulation.cpp
@@ -94,7 +94,7 @@ struct lif_chain: public recipe {
 
     std::vector<cell_connection> connections_on(cell_gid_type target) const {
         if (target) {
-            return {cell_connection({target-1, 0}, {target, 0}, weight_, delay_)};
+            return {cell_connection({target-1, 0}, 0, weight_, delay_)};
         }
         else {
             return {};
@@ -106,7 +106,7 @@ struct lif_chain: public recipe {
             return {};
         }
         else {
-            return {schedule_generator({target, 0}, weight_, triggers_)};
+            return {schedule_generator(0, weight_, triggers_)};
         }
     }