The way that Recast & Detour handles this is to include the agent's radius in the navmesh (to avoid having to post-process paths). In my game, I just apply velocity in the bearing of the waypoint until within a specific margin (0.01 m or so (> than 1 frame velocity error)) and then switch to the next waypoint. You could also check if the dot of the vector from the current waypoint to the npc position is greater than the distance between the current and next waypoint.
I avoid recalculating paths by only doing so if the target moves. You could extend this further by keeping track of entites within the same node and checking if they're in the path or not. To handle the case where the player leaves the navmesh, I keep track of the last node the player was within, then find the nearest neighbour according to the edge distance (assuming that I'm not currently in a node).