But it's also limiting, for example, you may want to run some perform an action before a resource is deleted and then you have two options:
a) create your own provider that will will handle the provisioning and deprovisioning under the hood
b) use provisioner (e.g. local-exec)
The first option is great if you have time and resources so create your own provider. The second option is what you're more likely to use if you are small and don't have a dedicated team. Also it's convenient if you can achieve 99% with existing providers just need to run one command, but doesn't always work (Terraform has many limitations regarding this).