diff --git a/mechanisms/mod/exp2syn.mod b/mechanisms/mod/exp2syn.mod
index da2d2ae639143b1732b714b20f5ce0c2cf1f2216..ea0cf025e9228216b4699161a2e574ca1d1dda6e 100755
--- a/mechanisms/mod/exp2syn.mod
+++ b/mechanisms/mod/exp2syn.mod
@@ -1,5 +1,5 @@
 NEURON {
-	POINT_PROCESS Exp2Syn
+	POINT_PROCESS exp2syn
 	RANGE tau1, tau2, e
 	NONSPECIFIC_CURRENT i
 }
@@ -11,8 +11,8 @@ UNITS {
 }
 
 PARAMETER {
-	tau1=.1 (ms) : <1e-9,1e9>
-	tau2 = 10 (ms) : <1e-9,1e9>
+	tau1 = .5 (ms) : <1e-9,1e9>
+	tau2 = 2  (ms) : <1e-9,1e9>
 	e=0	(mV)
 }
 
diff --git a/mechanisms/mod/expsyn.mod b/mechanisms/mod/expsyn.mod
index db1f6d6ed61a8b563141ea2516658b8f87a35637..16d10c5cf856cd87e50252dca2163d844588e2b9 100644
--- a/mechanisms/mod/expsyn.mod
+++ b/mechanisms/mod/expsyn.mod
@@ -1,5 +1,5 @@
 NEURON {
-    POINT_PROCESS ExpSyn
+    POINT_PROCESS expsyn
     RANGE tau, e
     NONSPECIFIC_CURRENT i
 }
diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp
index dfff77fa544cb68be9f0454dec8380c99aa530f8..ea5207dc732c69a42b3e66f1aa525a08cf69abca 100644
--- a/miniapp/miniapp.cpp
+++ b/miniapp/miniapp.cpp
@@ -425,8 +425,9 @@ mc::cell make_cell(int compartments_per_segment, int num_synapses) {
     auto distribution = std::uniform_real_distribution<float>(0.f, 1.0f);
     // distribute the synapses at random locations the terminal dendrites in a
     // round robin manner
+    nest::mc::parameter_list syn_default("expsyn");
     for (auto i=0; i<num_synapses; ++i) {
-        cell.add_synapse({2+(i%2), distribution(gen)});
+        cell.add_synapse({2+(i%2), distribution(gen)}, syn_default);
     }
 
     // add probes: 
diff --git a/src/cell.cpp b/src/cell.cpp
index 3a2d5672a12bb74e2e484765e16b93e870b2bd4b..01d681a7e080c8c0444fe0299820181d5154028e 100644
--- a/src/cell.cpp
+++ b/src/cell.cpp
@@ -201,16 +201,6 @@ std::vector<int> const& cell::segment_parents() const
     return parents_;
 }
 
-void cell::add_synapse(segment_location loc)
-{
-    synapses_.push_back(loc);
-}
-
-const std::vector<segment_location>& cell::synapses() const
-{
-    return synapses_;
-}
-
 // Rough and ready comparison of two cells.
 // We don't use an operator== because equality of two cells is open to
 // interpretation. For example, it is possible to have two viable representations
diff --git a/src/cell.hpp b/src/cell.hpp
index 744c9970e26af7f439f9cee7cfb2f88c96014624..1cb9b9f65dedbdcc4476c2b447eed1d1dea243ca 100644
--- a/src/cell.hpp
+++ b/src/cell.hpp
@@ -52,6 +52,11 @@ public:
     using index_type = int;
     using value_type = double;
     using point_type = point<value_type>;
+    
+    struct synapse_instance {
+        segment_location location;
+        parameter_list mechanism;
+    };
     struct probe_instance {
         segment_location location;
         probeKind kind;
@@ -138,9 +143,13 @@ public:
     //////////////////
     // synapses
     //////////////////
-    void add_synapse(segment_location loc);
-
-    const std::vector<segment_location>& synapses() const;
+    void add_synapse(segment_location loc, parameter_list p)
+    {
+        synapses_.push_back(synapse_instance{loc, std::move(p)});
+    }
+    const std::vector<synapse_instance>& synapses() const {
+        return synapses_;
+    }
 
     //////////////////
     // spike detectors
@@ -180,7 +189,7 @@ private:
     std::vector<stimulus_instance> stimulii_;
 
     // the synapses
-    std::vector<segment_location> synapses_;
+    std::vector<synapse_instance> synapses_;
 
     // the sensors
     std::vector<detector_instance> spike_detectors_;
diff --git a/src/fvm_cell.hpp b/src/fvm_cell.hpp
index 25c0ae9a0c67dd42e7bcf680a9b32a0c6070290b..05bce5bd02b57c8d8fe9a9c3e90962eeee8188b3 100644
--- a/src/fvm_cell.hpp
+++ b/src/fvm_cell.hpp
@@ -20,8 +20,6 @@
 #include <profiling/profiler.hpp>
 
 #include <vector/include/Vector.hpp>
-#include <mechanisms/expsyn.hpp>
-
 
 namespace nest {
 namespace mc {
@@ -185,10 +183,12 @@ private:
     /// the potential in mV in each CV
     vector_type voltage_;
 
+#if 0
     /// synapses
     using synapse_type =
         mechanisms::ExpSyn::mechanism_ExpSyn<value_type, size_type>;
-    std::size_t synapse_index_;
+#endif
+    std::size_t synapse_index_; // synapses at the end of mechanisms_, from here
 
     /// the set of mechanisms present in the cell
     std::vector<mechanism_type> mechanisms_;
@@ -342,6 +342,52 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell)
         );
     }
 
+    synapse_index_ = mechanisms_.size();
+
+    std::multimap<std::string, int> syn_map;
+    for (const auto& syn: cell.synapses()) {
+        syn_map.insert({syn.mechanism.name(), find_compartment_index(syn.location, graph)});
+    }
+
+    auto syn_i = syn_map.begin();
+    while (syn_i!=syn_map.end()) {
+        const auto& mech_name = syn_i->first;
+        auto& helper = nest::mc::mechanisms::get_mechanism_helper(mech_name);
+
+        auto span = syn_map.equal_range(mech_name);
+        auto num_comp = std::distance(span.first, span.second);
+
+        index_type compartment_index(num_comp);
+        for (auto p = compartment_index.data(); syn_i!=span.second; ++p, ++syn_i) {
+            *p = syn_i->second;
+        }
+
+        auto mech = helper->new_mechanism(voltage_, current_, compartment_index);
+        mech->set_areas(cv_areas_);
+        mechanisms_.push_back(std::move(mech));
+    }
+
+#if 0
+    // add the synapses
+    std::vector<size_type> synapse_indexes;
+    synapse_indexes.reserve(cell.synapses().size());
+    for(auto loc : cell.synapses()) {
+        synapse_indexes.push_back(
+            find_compartment_index(loc, graph)
+        );
+    }
+
+    mechanisms_.push_back(
+        mechanisms::make_mechanism<synapse_type>(
+            voltage_, current_, index_view(synapse_indexes)
+        )
+    );
+    synapse_index_ = mechanisms_.size()-1;
+    // don't forget to give point processes access to cv_areas_
+    mechanisms_[synapse_index_]->set_areas(cv_areas_);
+#endif
+
+
     /////////////////////////////////////////////
     // build the ion species
     /////////////////////////////////////////////
@@ -398,24 +444,6 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell)
         stimulii_.push_back( {idx, stim.clamp} );
     }
 
-    // add the synapses
-    std::vector<size_type> synapse_indexes;
-    synapse_indexes.reserve(cell.synapses().size());
-    for(auto loc : cell.synapses()) {
-        synapse_indexes.push_back(
-            find_compartment_index(loc, graph)
-        );
-    }
-
-    mechanisms_.push_back(
-        mechanisms::make_mechanism<synapse_type>(
-            voltage_, current_, index_view(synapse_indexes)
-        )
-    );
-    synapse_index_ = mechanisms_.size()-1;
-    // don't forget to give point processes access to cv_areas_
-    mechanisms_[synapse_index_]->set_areas(cv_areas_);
-
     // record probe locations by index into corresponding state vector
     for (auto probe : cell.probes()) {
         uint32_t comp = find_compartment_index(probe.location, graph);
diff --git a/src/mechanism_interface.cpp b/src/mechanism_interface.cpp
index f44d1f561d3efcc51b262b5bb32e0a95084bbcb5..680e8739d11ee0dad16890bb1088a1a7d4b774b5 100644
--- a/src/mechanism_interface.cpp
+++ b/src/mechanism_interface.cpp
@@ -6,6 +6,8 @@
 
 #include <mechanisms/hh.hpp>
 #include <mechanisms/pas.hpp>
+#include <mechanisms/expsyn.hpp>
+#include <mechanisms/exp2syn.hpp>
 
 
 namespace nest {
@@ -24,6 +26,16 @@ void setup_mechanism_helpers() {
         make_mechanism_helper<
             mechanisms::hh::helper<value_type, index_type>
         >();
+
+    mechanism_helpers["expsyn"] =
+        make_mechanism_helper<
+            mechanisms::expsyn::helper<value_type, index_type>
+        >();
+
+    mechanism_helpers["exp2syn"] =
+        make_mechanism_helper<
+            mechanisms::exp2syn::helper<value_type, index_type>
+        >();
 }
 
 mechanism_helper_ptr<value_type, index_type>&
diff --git a/tests/unit/test_mechanisms.cpp b/tests/unit/test_mechanisms.cpp
index aef84890275263ca7ef9570c1017864736a6f331..2e31f1139d25cb3e36bc1ff0b32a3ec8a4316a4b 100644
--- a/tests/unit/test_mechanisms.cpp
+++ b/tests/unit/test_mechanisms.cpp
@@ -6,7 +6,7 @@
 TEST(mechanisms, helpers) {
     nest::mc::mechanisms::setup_mechanism_helpers();
 
-    EXPECT_EQ(nest::mc::mechanisms::mechanism_helpers.size(), 2u);
+    EXPECT_EQ(nest::mc::mechanisms::mechanism_helpers.size(), 4u);
 
     // verify that the hh and pas channels are available
     EXPECT_EQ(nest::mc::mechanisms::get_mechanism_helper("hh")->name(), "hh");
diff --git a/tests/unit/test_synapses.cpp b/tests/unit/test_synapses.cpp
index ff79c1e6488a2534a03303aa30f05403bd4acdf9..9ad68c2444ef17d6f2b2355e3c388f76ca9220e6 100644
--- a/tests/unit/test_synapses.cpp
+++ b/tests/unit/test_synapses.cpp
@@ -3,6 +3,8 @@
 
 #include <cell.hpp>
 #include <fvm_cell.hpp>
+#include <mechanisms/expsyn.hpp>
+#include <mechanisms/exp2syn.hpp>
 
 // compares results with those generated by nrn/ball_and_stick.py
 TEST(synapses, add_to_cell)
@@ -18,29 +20,37 @@ TEST(synapses, add_to_cell)
     auto soma = cell.add_soma(12.6157/2.0);
     soma->add_mechanism(hh_parameters());
 
-    cell.add_synapse({0, 0.1});
-    cell.add_synapse({1, 0.2});
-    cell.add_synapse({0, 0.3});
+    parameter_list exp_default("expsyn");
+    parameter_list exp2_default("exp2syn");
+
+    cell.add_synapse({0, 0.1}, exp_default);
+    cell.add_synapse({1, 0.2}, exp2_default);
+    cell.add_synapse({0, 0.3}, exp_default);
 
     EXPECT_EQ(3u, cell.synapses().size());
-    EXPECT_EQ(cell.synapses()[0].segment, 0);
-    EXPECT_EQ(cell.synapses()[0].position, 0.1);
-    EXPECT_EQ(cell.synapses()[1].segment, 1);
-    EXPECT_EQ(cell.synapses()[1].position, 0.2);
-    EXPECT_EQ(cell.synapses()[2].segment, 0);
-    EXPECT_EQ(cell.synapses()[2].position, 0.3);
+    const auto& syns = cell.synapses();
+
+    EXPECT_EQ(syns[0].location.segment, 0);
+    EXPECT_EQ(syns[0].location.position, 0.1);
+    EXPECT_EQ(syns[0].mechanism.name(), "expsyn");
+
+    EXPECT_EQ(syns[1].location.segment, 1);
+    EXPECT_EQ(syns[1].location.position, 0.2);
+    EXPECT_EQ(syns[1].mechanism.name(), "exp2syn");
+
+    EXPECT_EQ(syns[2].location.segment, 0);
+    EXPECT_EQ(syns[2].location.position, 0.3);
+    EXPECT_EQ(syns[2].mechanism.name(), "expsyn");
 }
 
 // compares results with those generated by nrn/ball_and_stick.py
-TEST(synapses, basic_state)
+TEST(synapses, expsyn_basic_state)
 {
     using namespace nest::mc;
 
-    // setup global state for the mechanisms
-    nest::mc::mechanisms::setup_mechanism_helpers();
-
-    using synapse_type = mechanisms::ExpSyn::mechanism_ExpSyn<double, int>;
+    using synapse_type = mechanisms::expsyn::mechanism_expsyn<double, int>;
     auto num_syn = 4;
+
     synapse_type::index_type indexes(num_syn);
     synapse_type::vector_type voltage(num_syn, -65.0);
     synapse_type::vector_type current(num_syn,   1.0);
@@ -81,3 +91,54 @@ TEST(synapses, basic_state)
     EXPECT_EQ(ptr->g[1], 3.14);
     EXPECT_EQ(ptr->g[3], 1.04);
 }
+
+TEST(synapses, exp2syn_basic_state)
+{
+    using namespace nest::mc;
+
+    using synapse_type = mechanisms::exp2syn::mechanism_exp2syn<double, int>;
+    auto num_syn = 4;
+
+    synapse_type::index_type indexes(num_syn);
+    synapse_type::vector_type voltage(num_syn, -65.0);
+    synapse_type::vector_type current(num_syn,   1.0);
+    auto mech = mechanisms::make_mechanism<synapse_type>( voltage, current, indexes );
+
+    auto ptr = dynamic_cast<synapse_type*>(mech.get());
+
+    // parameters initialized to default values
+    for(auto e : ptr->e) {
+        EXPECT_EQ(e, 0.);
+    }
+    for(auto tau1: ptr->tau1) {
+        EXPECT_EQ(tau1, 0.5);
+    }
+    for(auto tau2: ptr->tau2) {
+        EXPECT_EQ(tau2, 2.0);
+    }
+
+    // should be initialized to NaN
+    for(auto factor: ptr->factor) {
+        EXPECT_NE(factor, factor);
+    }
+
+    // initialize state then check factor has sane (positive) value
+    // and A and B are zero
+    ptr->nrn_init();
+    for(auto factor: ptr->factor) {
+        EXPECT_GT(factor, 0.);
+    }
+    for(auto A: ptr->A) {
+        EXPECT_EQ(A, 0.);
+    }
+    for(auto B: ptr->B) {
+        EXPECT_EQ(B, 0.);
+    }
+
+    // call net_receive on two of the synapses
+    ptr->net_receive(1, 3.14);
+    ptr->net_receive(3, 1.04);
+
+    EXPECT_NEAR(ptr->A[1], ptr->factor[1]*3.14, 1e-6);
+    EXPECT_NEAR(ptr->B[3], ptr->factor[3]*1.04, 1e-6);
+}
diff --git a/tests/validation/validate_synapses.cpp b/tests/validation/validate_synapses.cpp
index 694887ce1cab4e27a322d48789200d5e07493608..42ace29c3393bb177b878ab3e8c6eb6de42d8676 100644
--- a/tests/validation/validate_synapses.cpp
+++ b/tests/validation/validate_synapses.cpp
@@ -46,7 +46,7 @@ struct result {
 };
 
 // compares results with those generated by nrn/simple_synapse.py
-TEST(simple_synapse, neuron_baseline)
+void run_neuron_baseline(const char* syn_type, const char* data_file)
 {
     using namespace nest::mc;
     using namespace nlohmann;
@@ -67,10 +67,11 @@ TEST(simple_synapse, neuron_baseline)
     dendrite->mechanism("membrane").set("r_L", 100);
     soma->mechanism("membrane").set("r_L", 100);
 
-    // add stimulus
-    cell.add_synapse({1, 0.5});
+    // add synapse
+    parameter_list syn_default(syn_type);
+    cell.add_synapse({1, 0.5}, syn_default);
 
-    // add porbes
+    // add probes
     auto probe_soma = cell.add_probe({0,0}, probeKind::membrane_voltage);
     auto probe_dend = cell.add_probe({1,0.5}, probeKind::membrane_voltage);
 
@@ -82,7 +83,7 @@ TEST(simple_synapse, neuron_baseline)
     };
 
     // load data from file
-    auto cell_data = testing::g_validation_data.load("simple_exp_synapse.json");
+    auto cell_data = testing::g_validation_data.load(data_file);
     EXPECT_TRUE(cell_data.size()>0);
     if(cell_data.size()==0) return;
 
@@ -164,3 +165,12 @@ TEST(simple_synapse, neuron_baseline)
     }
 }
 
+TEST(simple_synapse, expsyn_neuron_baseline) {
+    SCOPED_TRACE("expsyn");
+    run_neuron_baseline("expsyn","simple_exp_synapse.json");
+}
+
+TEST(simple_synapse, exp2syn_neuron_baseline) {
+    SCOPED_TRACE("exp2syn");
+    run_neuron_baseline("exp2syn","simple_exp2_synapse.json");
+}