Using Azure Devops with Git Workflow
Most answers to these questions are going be subjective and influenced by your particular organization's workflows and culture. Little of this response if more than just my own opinion and experience and much is not really specific to Azure DevOps but can be applied to any build and release orchestration tooling.

Azure DevOps itself has very little to do with your chosen workflow apart from it being the common remote for the team and the source for pull requests etc. What source workflow you use is highly dependent on your individual situation. The number of people on your team doing simultaneous work, how much possible conflict there is between feature development efforts, your rate of release, complexity of code/projects, and philosophies about release management to name a few. Much has been written about various source management workflows. In the realm of Git, of course there's the over 10 year old GitFlow approach (note the recent update) and GitHubFlow. I won't regurgitate what they or the numerous other writings suggest about what flow to use. Your team needs to research the options and evaluate what is most applicable.

It certainly is not a bad practice to do a build for every PR. If developers are following good practices where feature branches originate from the merge target, there is a high probability that any testing/compiling they did in code from those branches will essentially match what will eventually be merged. However, that's never a guarantee so having the ability to do a pre merge PR build is a very helpful feature of ADO. And ADO can be configured to required a passing PR build before merge. You can also deploy PR builds if you want to support initial manual testing and/or more complex integration of a PR prior to merge.

This again will be a choice driven by your team and situation. Do you want every feature merge to result in a build? If you are practicing Agile, you may have work items that require manual testing as part of the definition of done. In that case, getting builds out immediately after code is complete could be imperative to forward progress. I follow a continuous integration approach and have builds trigger immediately upon commits/merges to the &quot;typical&quot; branch of work in progress (often that will be the development branch). The sooner you discover a problem, whether that is a compile error of the merged code, a unit test failure, or a manual integration test bug the better. Every minute you wait to fix an issue is compounded into more time resolving it later as the work fades from peoples' minds.

I have typically followed the philosophy that &quot;what I deploy to production should be what we tested&quot;. While theoretically, if you do 2 builds of the same exact source code you should get the same result, there's no guarantee of that. Particularly now with the use of public packages/modules and the ability to allow flexibility with what versions are consumed, it's not an unreasonable possibility that a later build will result in different artifacts, for example, but pulling in a newly updated version of a dependency. For some very real perspective on this, see this article about how the &quot;internet broke&quot; some years ago. I work in the healthcare industry which has very strict rules that drive our implementation approach. We need to deploy just what was tested and approved to the production environment. If we did a fresh build for production release that introduced a changed library with an unknown security vulnerability, we could get into serious hot water.  I follow the practice of having a build pipeline do the actual build of final artifacts which become the singular source for deployments for testing and final promotion to production. ADO makes this very simple by publishing the artifacts into its own internal storage and providing those as an artifact source for a release pipeline. You can then deploy that (and additional) artifacts to each release stage of your pipeline. One key factor to consider is environment configuration management. Depending on your deployment target, you'll need to take into account how to influence the runtime configuration. My organization still deploys .NET applications to traditional IIS web servers using file copy. This requires an explicit step to apply config transformations for the application based on the target environment. This approach can be enhanced by using a separate artifact source for the transformation to better implement the good DevOps practice of separation of concerns (environment agnostic build artifacts vs. env specific configuration; env configuration, including secrets, can be retrieved from a different, more protected source so they are not in the application code repository). If you are deploying to a docker image, your docker runtime environment can drive environment specific settings for the container instances. Deploying to a cloud application host service? Use its instance configuration tooling, such as the app service/slot specific configuration settings in Azure. Applications like React, however, take a different approach that typically dictates that you do a build for the target environment since environment driven values are bundled into the deployed artifacts. I'm not a fan of this as it breaks my core philosophy of &quot;build once, run anywhere&quot;. But there are some solutions to help make such builds environment agnostic.