A deploy script that fixes ownership runs once per deploy and does nothing about a directory created afterwards by something else.
# /etc/tmpfiles.d/app.conf
d /var/www/app/storage/logs 0750 www-data www-data 30d
d /var/www/app/storage/cache 0750 www-data www-data -
d /run/app 0755 www-data www-data -
# systemd-tmpfiles --create applies it at boot and on a
# timer, and the 30d on the first line is an age-based
# cleanup that replaces a cron job.
The age field turning it into a cleanup mechanism is the part that is underused — a logs directory with a retention declared next to its permissions is one file instead of a chown, a logrotate entry and a cron job. It also survives a directory being deleted and recreated, which a deploy-time chown does not.