Debs work really well when they are shipped as part of the distribution deb archive itself. They work really badly when third parties try to use them to provide add-on software to an existing distribution release.
The main problem that Snaps solve is this latter case: when third parties are trying to ship directly into someone's distribution installation[1].
Often third party debs appear to work OK, but then break future distribution upgrades. By then users have forgotten about the third party software that has hacked itself into their system, and blame the distribution for their upgrade failure. The problem is that distribution debs are designed to provide metadata about what has changed so that the package manager can accommodate. But it's not possible for distribution debs to be aware of the third party debs to handle those changes. So things break.
The breakages caused by debs aren't just limited to future distribution upgrades. A bad third party deb package can break your entire system. We routinely get reports where it turns out that this is what happened to our users!
There's also the problem of dependencies. If a third party app needs a bunch of dependencies, then they can't realistically bump those dependencies on the system as a whole without regressing all the other apps that need older versions of that dependency. So they have to bundle their dependencies, and this is something else that regular deb tooling doesn't handle well. You can theoretically construct a deb that bundles all its dependencies, but then that's exactly what snaps and snap tooling handles better - that's half the point. Nix only partially solves the problem by better supporting concurrent installation of multiple versions of those dependencies. But those concurrent versions would still each have to be maintained; that's something that distributions try to avoid by picking one version of each dependency and making the entire distribution release work with just that one. Moving that maintenance responsibility to each third party app developer, and having the packages bundle their dependencies, is the other solution. This was already happening with deb packages like for Firefox. Firefox upstream bundles nearly everything, and the debs (eg. in Debian) do the same for most of their dependencies. Snaps just call a spade a spade and are designed around it.
You also wouldn't really expect a third party app to have access to everything on your system. Say for example you download and install some game app to try out. Do you really want it to have access to your online banking browser session? The game developer might not secure their development infrastructure as if someone's trying to steal their users' money, because that's expensive and they're only shipping a game. But if you install their game, then that's what you risk. That game developer's infrastructure is suddenly an attack vector for an adversary that wants to get to your online banking session. On iOS and Android, each app only has system-mediated access to everything outside its sandbox. Debs fundamentally cannot provide this separation, so if you install third party debs then you're giving all those third parties access to everything, which really is unacceptable in modern security practice. Snaps give you that sandboxing.
So that's what snaps are for: 1) bundling dependencies, because that's necessary in world of third party software that ships independently of the distribution; and 2) sandboxing, because that's necessary in a world of third party software if you don't want to give all those third parties and their adversaries root on your system.
If you don't want third party apps, and only want what your distribution ships in a curated manner, then you don't really need snaps. But consider that Firefox is essentially a third party, non-curated app, regardless of your distribution or how it was packaged! See [1] below.
Snaps are also immutable, which really helps with stability and upgrade and revert cases. This is more relevant for snap-only systems like in IoT, not the Ubuntu desktop. In an IoT deployment you can't tell the user to run "apt-get -f install" to fix up the system because power got interrupted during an upgrade - because that's how debs work.
In years gone by, Ubuntu tried really hard to make third party debs work. But it didn't work for various reasons. In the meantime, it became the norm for third parties to ship debs together with all of their problems, since there was nothing better possible at the time. This is what snaps solve.
Disclosure: I work for Canonical. But here I am speaking for myself, not my employer. I'm not involved in the design of snaps, but as a distribution developer, it's clear to me what problems they solve.
[1] Packages like Firefox also use snaps because even as a deb it's really not the case that Firefox is curated by the distribution and mostly unchanged after release any more. So it suffers from mostly all the same problems that third party debs do.
In my reply I focused on why we need a bundled, sandboxed packaging format in the first place, since many people are sceptical just about that. So you're right in that I didn't go into any of the differences.
Snaps solve a bunch of problems that are out of scope of Flatpaks, such as CLI apps and the packaging of kernels and other hardware-level pieces. This allows for an entirely snap-based system that is immutable and atomically updated, which is essential for IoT devices to be reliable.
If you look at the history of snaps, they are an evolution of click packaging, which were created for the Ubuntu phone that is no more. But the history goes back further than that - back to Ubuntu's App Review Board and (deb based) third party app packaging system, which failed for exactly the reason that deb is an unsuitable packaging format for third party apps.
If you look at the history of Flatpaks, you'll find that their initial release was at a similar time to snaps. But given that they don't solve a bunch of problems that snaps do, what was/is Canonical supposed to do? Ditch snaps entirely and drop their IoT support? Integrate IoT support into Flatpaks? Do Flatpak upstream even want that? Look at the history of Canonical wanting to ehnance GNOME, and the history of how Unity began, to see how that doesn't seem like it would be a practical way of delivering functionality to users in a reasonable period of time.
Consider that it is Ubuntu that is at the centre of this third party app packaging problem. It's Ubuntu that everybody targets first with their third party debs. For the same underlying reason, it's Ubuntu that gets more user support requests because of bad third party debs than every other distribution. It makes sense that Ubuntu developers are best placed to understand the problem and develop a solution.
So yes, we've ended up with two parallel contenders. But I don't think it's reasonable for Canonical to have done anything differently in regard to Flatpak. It appeared at the same time while Canonical had already been working away at the problem for years, doesn't solve or even try to solve all the problems that snaps are designed to solve, and those problems appear to be out of the scope of Flatpak anyway. As much as critics frame them as like-for-like options that Canonical could just decide to switch over, they simply aren't and thus "simply switching" doesn't even make sense.
As for "another one already exists", that statement could just as well apply the other way round: look at the timelines!
> Nix only partially solves the problem by better supporting concurrent installation of multiple versions of those dependencies. But those concurrent versions would still each have to be maintained
How so? Every dependency of every dependency is in the nix store and they’re all immutable. A nix package installed will work forever because its environment can’t change. Am I not right?
Bugs and security issues are found from time to time. When that happens, every occurrence in use needs an update. If ten different incompatible versions of a package are in use, they all need to be replaced. That's more work than one per traditional distribution release.
The main problem that Snaps solve is this latter case: when third parties are trying to ship directly into someone's distribution installation[1].
Often third party debs appear to work OK, but then break future distribution upgrades. By then users have forgotten about the third party software that has hacked itself into their system, and blame the distribution for their upgrade failure. The problem is that distribution debs are designed to provide metadata about what has changed so that the package manager can accommodate. But it's not possible for distribution debs to be aware of the third party debs to handle those changes. So things break.
The breakages caused by debs aren't just limited to future distribution upgrades. A bad third party deb package can break your entire system. We routinely get reports where it turns out that this is what happened to our users!
There's also the problem of dependencies. If a third party app needs a bunch of dependencies, then they can't realistically bump those dependencies on the system as a whole without regressing all the other apps that need older versions of that dependency. So they have to bundle their dependencies, and this is something else that regular deb tooling doesn't handle well. You can theoretically construct a deb that bundles all its dependencies, but then that's exactly what snaps and snap tooling handles better - that's half the point. Nix only partially solves the problem by better supporting concurrent installation of multiple versions of those dependencies. But those concurrent versions would still each have to be maintained; that's something that distributions try to avoid by picking one version of each dependency and making the entire distribution release work with just that one. Moving that maintenance responsibility to each third party app developer, and having the packages bundle their dependencies, is the other solution. This was already happening with deb packages like for Firefox. Firefox upstream bundles nearly everything, and the debs (eg. in Debian) do the same for most of their dependencies. Snaps just call a spade a spade and are designed around it.
You also wouldn't really expect a third party app to have access to everything on your system. Say for example you download and install some game app to try out. Do you really want it to have access to your online banking browser session? The game developer might not secure their development infrastructure as if someone's trying to steal their users' money, because that's expensive and they're only shipping a game. But if you install their game, then that's what you risk. That game developer's infrastructure is suddenly an attack vector for an adversary that wants to get to your online banking session. On iOS and Android, each app only has system-mediated access to everything outside its sandbox. Debs fundamentally cannot provide this separation, so if you install third party debs then you're giving all those third parties access to everything, which really is unacceptable in modern security practice. Snaps give you that sandboxing.
So that's what snaps are for: 1) bundling dependencies, because that's necessary in world of third party software that ships independently of the distribution; and 2) sandboxing, because that's necessary in a world of third party software if you don't want to give all those third parties and their adversaries root on your system.
If you don't want third party apps, and only want what your distribution ships in a curated manner, then you don't really need snaps. But consider that Firefox is essentially a third party, non-curated app, regardless of your distribution or how it was packaged! See [1] below.
Snaps are also immutable, which really helps with stability and upgrade and revert cases. This is more relevant for snap-only systems like in IoT, not the Ubuntu desktop. In an IoT deployment you can't tell the user to run "apt-get -f install" to fix up the system because power got interrupted during an upgrade - because that's how debs work.
In years gone by, Ubuntu tried really hard to make third party debs work. But it didn't work for various reasons. In the meantime, it became the norm for third parties to ship debs together with all of their problems, since there was nothing better possible at the time. This is what snaps solve.
Disclosure: I work for Canonical. But here I am speaking for myself, not my employer. I'm not involved in the design of snaps, but as a distribution developer, it's clear to me what problems they solve.
[1] Packages like Firefox also use snaps because even as a deb it's really not the case that Firefox is curated by the distribution and mostly unchanged after release any more. So it suffers from mostly all the same problems that third party debs do.