Macros will work but have less capability in terms of error handling. I think I've only ever had one macro in any of my production databases because I converted all other macros to VBA code. It's easy, there's a ribbon item for that.
If you have a form that is open, it can be the host for a timed event running code. The fact that the form is hidden is not a barrier to running code. Note that if you have more than one periodic-run element, you cannot have multiple timer routines in the same form because you have only one timer slot in the form's event code. So if you found yourself in that case (not saying you have that here), you would either have to write a smart timer routine or you would have to launch some small forms that were never visible but that had the required timer routines, each with their own timing. I would recommend a smart single timer routine if that ever happened to you.
As a matter of style, an issue of data protection, but surely not an absolute requirement, my databases that actually had users logging in always had a switchboard form. I ran my timer code from the switchboard.
I did that because it is not a secure situation to allow users to see the infrastructure that is visible in the navigation panel. If they can see it, natural curiosity will cause them to ... futz ... with it and bang/zoom! There goes your database. Threats of dire consequences didn't stop the users on my first database back in Ac97 days. So in my later databases, users could ONLY see the switchboard from, from which they could launch functional forms with a command button. (The button wizard includes "Open a Form" as one of its options, so it is easy to build this.)
In deployment, you need to declare the switchboard (some would prefer to call it a "dispatcher" form) as your default opening form. In its Form_Open code, you immediately tend to issues of security such as (if required) popping up the login form, turning off the ribbon and navigation features, etc. If you choose that direction, search this forum for articles with titles like "Securing a Database."
Note also that if you require a login but have a domain-based environment, your users have already logged in. You can find out who they are by the Environ("Username") function and look up the domain name in a Users table. Then you could have other data in that table to allow the code behind each command button to decide whether to function for that person, if you had the case of some folks doing only limited operations.
If you have a dispatcher, that kind of functional selectivity is trivial (if a bit tedious).