For static geometric objects you never want to duplicate the mesh in memory. For the spike you just have a single spike mesh loaded in memory once and stored into opengl once (and then removed from your main memory if you can get away with it). You are definitely taking the right approach. There has to be a way to get the rotation data out of the map data (I'm not familiar with your map data at all though).
I don't know what your visual goals are, but the number of polys per item that you mention sound really high to me. a 2k poly coin is pretty excessive

That's more than enough polys to model a good looking humanoid character, much less a coin. 300 polys is more reasonable but I would expect a 3d disc coin to be in the neighborhood of 50-100 polys depending on how many 'sides' your circles have. 400 polys for a spike sounds excessive. When you say spike I think of a skinny cone, which could easily be modelled with 6 sides (6 polys!). If the spike is all bendy or whatnot then of course it requires more. These are the kinds of numbers I would expect for a realtime action game with lots of these objects all over the place.
With our theoretical 100k poly per frame target, you're looking at rendering about 160 coins and 125 spikes and nothing else.
Using the instancing approach of duplicated geometry is how professional games get their poly counts up past 100k to the half million range per frame and still use reasonably detailed models.