diff --git a/src/hdf5-writer.hh b/src/hdf5-writer.hh
index 02de2b278b542448491920e1244bf4726f778155..85a08e1e3b74618edfc1303b4a720be88b9653b7 100644
--- a/src/hdf5-writer.hh
+++ b/src/hdf5-writer.hh
@@ -8,7 +8,6 @@
 #include "hdf5/frictionalboundary-writer.hh"
 #include "hdf5/iteration-writer.hh"
 #include "hdf5/patchinfo-writer.hh"
-#include "hdf5/restart-io.hh"
 #include "hdf5/surface-writer.hh"
 #include "hdf5/time-writer.hh"
 
@@ -32,8 +31,8 @@ class HDF5Writer {
         patchInfoWriter_(file_, vertexBasis, frictionalBoundary, weakPatch),
 #endif
         surfaceWriter_(file_, vertexCoordinates, surface),
-        frictionalBoundaryWriter_(file_, vertexCoordinates, frictionalBoundary),
-        restartWriter_(file_, vertexCoordinates.size()) {
+        frictionalBoundaryWriter_(file_, vertexCoordinates,
+                                  frictionalBoundary) {
   }
 
   template <class Friction>
@@ -53,10 +52,6 @@ class HDF5Writer {
     iterationWriter_.write(programState.timeStep, iterationCount);
   }
 
-  void writeRestart(ProgramState const &programState) {
-    restartWriter_.write(programState);
-  }
-
 private:
   HDF5::Grouplike &file_;
 
@@ -67,7 +62,5 @@ class HDF5Writer {
 #endif
   SurfaceWriter<ProgramState, GridView> surfaceWriter_;
   FrictionalBoundaryWriter<ProgramState, GridView> frictionalBoundaryWriter_;
-
-  RestartIO<ProgramState> restartWriter_;
 };
 #endif
diff --git a/src/hdf5/restart-io.cc b/src/hdf5/restart-io.cc
index 8fe3c59a504c41a4e0187019854c3a63c921120a..5143947d8c69a6318605b747803a14bc7c8ba3d3 100644
--- a/src/hdf5/restart-io.cc
+++ b/src/hdf5/restart-io.cc
@@ -5,18 +5,17 @@
 #include "restart-io.hh"
 
 template <class ProgramState>
-RestartIO<ProgramState>::RestartIO(HDF5::Grouplike &file, size_t vertexCount)
-    : group_(file, "restarts"),
-      displacementWriter_(group_, "displacement", vertexCount,
+RestartIO<ProgramState>::RestartIO(HDF5::Grouplike &group, size_t vertexCount)
+    : displacementWriter_(group, "displacement", vertexCount,
                           Vector::block_type::dimension),
-      velocityWriter_(group_, "velocity", vertexCount,
+      velocityWriter_(group, "velocity", vertexCount,
                       Vector::block_type::dimension),
-      accelerationWriter_(group_, "acceleration", vertexCount,
+      accelerationWriter_(group, "acceleration", vertexCount,
                           Vector::block_type::dimension),
-      stateWriter_(group_, "state", vertexCount),
-      weightedNormalStressWriter_(group_, "weightedNormalStress", vertexCount),
-      relativeTimeWriter_(group_, "relativeTime"),
-      relativeTimeIncrementWriter_(group_, "relativeTimeIncrement") {}
+      stateWriter_(group, "state", vertexCount),
+      weightedNormalStressWriter_(group, "weightedNormalStress", vertexCount),
+      relativeTimeWriter_(group, "relativeTime"),
+      relativeTimeIncrementWriter_(group, "relativeTimeIncrement") {}
 
 template <class ProgramState>
 void RestartIO<ProgramState>::write(ProgramState const &programState) {
diff --git a/src/hdf5/restart-io.hh b/src/hdf5/restart-io.hh
index 94b60d67f72e858cfdda918a8a452186fcbd4394..f90b01a7e983dd2d97b8a02cf6f658c0f58648db 100644
--- a/src/hdf5/restart-io.hh
+++ b/src/hdf5/restart-io.hh
@@ -9,15 +9,13 @@ template <class ProgramState> class RestartIO {
   using Vector = typename ProgramState::Vector;
 
 public:
-  RestartIO(HDF5::Grouplike &file, size_t vertexCount);
+  RestartIO(HDF5::Grouplike &group, size_t vertexCount);
 
   void write(ProgramState const &programState);
 
   void read(size_t timeStep, ProgramState &programState);
 
 private:
-  HDF5::Group group_;
-
   HDF5::SequenceIO<2> displacementWriter_;
   HDF5::SequenceIO<2> velocityWriter_;
   HDF5::SequenceIO<2> accelerationWriter_;
diff --git a/src/one-body-problem.cc b/src/one-body-problem.cc
index 14139f808bf467490964be8ae9929e24ad0facce..d4d5ed5608cff4b550b79af8e7cc759a8a30b527 100644
--- a/src/one-body-problem.cc
+++ b/src/one-body-problem.cc
@@ -176,15 +176,29 @@ int main(int argc, char *argv[]) {
           _ell += gravityFunctional;
         };
 
-    ProgramState<Vector, ScalarVector> programState(leafVertexCount);
-    auto const firstRestart = parset.get<size_t>("restarts.first");
-    auto const restartSpacing = parset.get<size_t>("restarts.spacing");
-    auto const restartTemplate = parset.get<std::string>("restarts.template");
-
-    HDF5::File ioFile("output.h5");
-    if (firstRestart != 0)
-      RestartIO<ProgramState<Vector, ScalarVector>>(ioFile, leafVertexCount)
-          .read(firstRestart, programState);
+    using MyProgramState = ProgramState<Vector, ScalarVector>;
+    MyProgramState programState(leafVertexCount);
+    auto const firstRestart = parset.get<size_t>("io.restarts.first");
+    auto const restartSpacing = parset.get<size_t>("io.restarts.spacing");
+    auto const writeRestarts = parset.get<bool>("io.restarts.write");
+    auto const writeData = parset.get<bool>("io.data.write");
+    bool const handleRestarts = writeRestarts or firstRestart > 0;
+
+    auto dataFile =
+        writeData ? std::make_unique<HDF5::File>("output.h5") : nullptr;
+    auto restartFile = handleRestarts
+                           ? std::make_unique<HDF5::File>(
+                                 "restarts.h5",
+                                 writeRestarts ? HDF5::Access::READWRITE
+                                               : HDF5::Access::READONLY)
+                           : nullptr;
+    auto restartIO = handleRestarts
+                         ? std::make_unique<RestartIO<MyProgramState>>(
+                               *restartFile, leafVertexCount)
+                         : nullptr;
+
+    if (firstRestart > 0) // automatically adjusts the time and timestep
+      restartIO->read(firstRestart, programState);
     else
       programState.setupInitialConditions(parset, computeExternalForces,
                                           matrices, myAssembler, dirichletNodes,
@@ -205,24 +219,30 @@ int main(int argc, char *argv[]) {
         vertexCoordinates[vertexMapper.index(v)] = geoToPoint(v.geometry());
     }
 
-    HDF5Writer<ProgramState<Vector, ScalarVector>,
-               typename MyAssembler::VertexBasis, GridView>
-        hdf5Writer(ioFile, vertexCoordinates, myAssembler.vertexBasis, surface,
-                   frictionalBoundary, weakPatch);
-    MyVTKWriter<typename MyAssembler::VertexBasis,
-                typename MyAssembler::CellBasis> const
-        vtkWriter(myAssembler.cellBasis, myAssembler.vertexBasis, "obs");
+    using MyVertexBasis = typename MyAssembler::VertexBasis;
+    auto dataWriter =
+        writeData ? std::make_unique<
+                        HDF5Writer<MyProgramState, MyVertexBasis, GridView>>(
+                        *dataFile, vertexCoordinates, myAssembler.vertexBasis,
+                        surface, frictionalBoundary, weakPatch)
+                  : nullptr;
+    MyVTKWriter<MyVertexBasis, typename MyAssembler::CellBasis> const vtkWriter(
+        myAssembler.cellBasis, myAssembler.vertexBasis, "obs");
 
     IterationRegister iterationCount;
     auto const report = [&](bool initial = false) {
-      hdf5Writer.reportSolution(programState, *myGlobalFriction);
-      if (!initial)
-        hdf5Writer.reportIterations(programState, iterationCount);
-
-      if (!initial and programState.timeStep % restartSpacing == 0)
-        hdf5Writer.writeRestart(programState);
+      if (writeData) {
+        dataWriter->reportSolution(programState, *myGlobalFriction);
+        if (!initial)
+          dataWriter->reportIterations(programState, iterationCount);
+        dataFile->flush();
+      }
 
-      ioFile.flush();
+      if (writeRestarts and !initial and
+          programState.timeStep % restartSpacing == 0) {
+        restartIO->write(programState);
+        restartFile->flush();
+      }
 
       if (parset.get<bool>("io.printProgress"))
         std::cout << "timeStep = " << std::setw(6) << programState.timeStep
@@ -230,7 +250,7 @@ int main(int argc, char *argv[]) {
                   << ", tau = " << std::setw(12) << programState.relativeTau
                   << std::endl;
 
-      if (parset.get<bool>("io.writeVTK")) {
+      if (parset.get<bool>("io.vtk.write")) {
         ScalarVector stress;
         myAssembler.assembleVonMisesStress(body.getYoungModulus(),
                                            body.getPoissonRatio(),
diff --git a/src/one-body-problem.cfg b/src/one-body-problem.cfg
index 21c7d5fcfcc1763c93e1d33512183e0c61b6d9c4..d970f5e93a5f6dc77c3be6e3f053cf4a85e73529 100644
--- a/src/one-body-problem.cfg
+++ b/src/one-body-problem.cfg
@@ -2,8 +2,12 @@
 gravity         = 9.81  # [m/s^2]
 
 [io]
+data.write      = true
 printProgress   = false
-writeVTK        = false
+restarts.first  = 0
+restarts.spacing= 20
+restarts.write  = true
+vtk.write       = false
 
 [problem]
 finalTime       = 1000  # [s]
@@ -35,11 +39,6 @@ b               = 0.017 # [ ]
 a               = 0.020 # [ ]
 b               = 0.005 # [ ]
 
-[restarts]
-template = restart_%06d
-first = 0
-spacing = 20
-
 [timeSteps]
 scheme = newmark