As you have two separate (sets of) parameters to train: What you’d typically do is to define two optimizers (for users and items) and set the other’s requires_grad to false when computing an update for either.
The next question could be whether you get significantly worse results when computing simultaneous updates instead of alternating ones, I must admit I’d probably try that, too.
Best regards
Thomas