Ok thanks guys.
I am using the idea suggested - get the size of the chunk before allocating a vertex buffer. Memory usage went down from ~300MB for 25 chunks (yes, a hell of a lot) to ~22MB. Much better. For 256 chunks (16x16) it takes ~40MB memory - shows how much savings you get from culling unseen faces..
The performance loss from creating new vertex/index buffers whenever a chunk is modified is negligible. I placed blocks as fast as I could click, and the FPS remained pretty much constant at around 170FPS. I might implement some feature later which makes the vertex/index buffers slightly too big (room for about 50 more blocks), then extend it when it gets full, so I am doing a lot less buffer re-allocations.
Re-creating the buffers when I modify chunks also means I can make static buffers, which should give a performance gain above using dynamic buffers.
Once again, thanks for the advice.