Someone asked this question a while back, so I thought I'd share the answer with everyone.
To understand the question being asked here, you should be familiar with Continuous Integration in Salesforce. Assuming you are familiar with it, let's discuss the differences between these 2 patterns.
I'm going to start by explaining these concepts in the broader context of software development, and then I'll share some thoughts on how they apply to Salesforce development and Salesforce CI/CD.
A main branch
First, both patterns (like in most other Git branching strategies) have a "main" branch, also known as the mainline or "master."
This branch represents what your production version/environment should look like.
At what point the mainline represent the actual production version is the difference between these 2 patterns.
In Continuous Delivery, every commit to the mainline should be "releasable." This means that if something is in the mainline, it can be released at any time. The mainline shouldn't have anything that cannot be released (i.e., because it's buggy or fails to deploy/compile).
You may have heard/read the phrase "mainline always being in a deployable state." That above is what this phrase means.
When the entire mainline or specific features are actually deployed to production is a business decision.
In Continuous Deployment, every commit to the mainline actually triggers a production deployment. In this sense, Continuous Deployment builds on top of Continuous Delivery.
A good quote
Here's a good quote from Martin Fowler that summarises the differences:
In Salesforce CI/CD
Let's now see how these 2 concepts can be applied (or not) to a Salesforce development context.
Continuous Delivery in Salesforce
I find this pattern is not widely used in Salesforce development.
For most Salesforce teams, the source of truth is the
main branch, i.e.
main represents what's already running in your production org. Very few teams use
main as a representation of what has been approved by the business but not released to production yet.
Something a little bit more similar to Continuous Delivery is having a pre-prod or staging sandbox, where we assume features are already approved and working (in a deployable state), just waiting to be released.
One could make the stretch that a pre-prod sandbox can act as a non-git branch, in the sense that it originated from production. So if we treat a pre-prod sandbox as our
main branch, then we could argue we are practicing some form of Continuous Delivery. Again, that's a stretch.
Also, notice that the emphasis here is on releasing and not deploying. In a Continuous Delivery model, we are encouraged to deploy features yet not release them until a later time. To do this, we need to use feature flags and branch by abstraction; these are patterns that are not easy to use in Salesforce, and it's something to discuss in a future article.
Continuous Deployment in Salesforce
This is more achievable because all that needs to happen is when a commit is made on
main, a deployment to production is triggered, which deploys the
main branch (along with the new commit that was just merged).
This is a pretty standard feature of many Salesforce DevOps vendors and something that I use in my own CI/CD pipeline.
That's it. Hopefully, this made these 2 concepts a little easier to understand. Here are some other resources I recommend for further learning.