It is never okay to use a variable-step rate
Just to reduce the hardness of L.S.'s stance here; all the console games that I've ever worked on (up until my indie project) have used a variable time-step. If your simulation can tolerate a wide range of delta-time values, and gameplay isn't affected by the varying quality of integration, then variable time-step result in a far simpler codebase...
I'm currently doing game engine contracting for a console games company, and have tried to convince them that they should really be using fixed time-step plus game-state interpolation... but have been unable to provide an objective argument to sway them so far. Their variable-rate system is working perfectly fine for them, and as we say, if it ain't broke, don't fix it.
Making a separate render thread is non-trivial and requires some experience.
While this is true, switching from variable-time-step to fixed-time-step + interpolation lays a lot of the foundations. The game-state interpolation system basically requires that the renderer's input data is separated from the live game-state data, which is required for a good multi-thread implementation :)
If you need a cap, limit the number of updates you can do in a frame, but each update still needs to be of a fixed amount of time. You have to be fine with having your game slow down and drop frames for this to work
You should generally do this in a variable time-step system too -- cap the amount of time that a single frame is allowed to simulate -- as the quality of the integration will be pretty terrible if you try to simulate too much time in one go. As in the fixed-time-step case, this will cause your game to go into slow motion if the actual framerate is too low.
Out of curiosity, how does one maintain separate threads for game logic & physics effectively? I would assume both want to be touching the same bits of data - to a large extent.
The key to any good multithreading system is ensuring that no two threads ever need to share the same mutable data :)
For update/render, this means forming a pipeline where each frame, the update task generates a fresh blob of immutable data which is consumed by the render task.
The other drawback of fixed-step is you don't know how many update steps you may take
It's the same as in a variable-step architecture. You measure how long the previous frame took, and then advance the simulation by that amount of time next frame.