Re-rendering happens because you changed the actual object reference while retrieving the data, and angular time ngForre-painted all the DOM nodes. For such cases, you can use it trackByhere, where you can make your *ngForsmarter.
trackBy , , message.id
<message *ngFor="let message of messages | async;trackBy:trackByFn" [message]="message"></message>
trackByFn(message: any){
return message != null ? message.id: null;
}