Conceptually, you are right. Checkpoints are taken at every operator at the same "logical" time.
It is not important, that each operator checkpoints at the same wallclock time. Instead, the need to take a checkpoint when they have processed the same input.
This is implemented with so-called Checkpoint Barriers, which are special records that are injected at the sources.
[Simplification] When an operator receives a barrier it performs a checkpoint. [/Simplification]
This way, we do not need to pause the processing of all operators but can perform the checkpoints locally for each operator.
This page of the Internal docs should help to understand how the mechanism works in detail .