You can neatly put all your logic into a signle class, and then have a nice little factory that looks at @ARGV.

If your class has prod configs as defaults, then your crontab looks like this:

* * * * * perl -MMyApp::Script::CleanupExpiredEntries \
                -E'MyApp::Script::CleanupExpiredEntries->new_from_args->run'

Because you don't have any code in a bin/run-me script, you can neatly write tests for all your functions by either sub-classing your ::Script to replace your database access logic or by by straight-up replacing the method for the duration of your sub-test with

{
    local *MyApp::Script::CleanupExpiredEntries::fetch_from_db = sub  { ...}
    ...
}

The most notable downside is that some day someone might introduce some code that uses Log::Log4perl, and a config config that references $0:

log4perl.appender.LOGFILE.filename=sub {
    my $name = ( map s{ [.]pl $ }{}xr, split m{/}, $0 )[-1];
    "/var/log/$name/$name.log" }

which means you'll get a mail a minute saying:

 Can't sysopen /var/log/-e/-e.log (No such file or directory)
    at /usr/share/perl5/Log/Log4perl/Appender/File.pm line 140.

which might not be the kind of thing you want to see after taking a couple of days off.