If you really want to be as accurate as possible, and you are sure that your task will take less time than the interval that you want to complete, you can have one lengthy process, rather than run the process every 10 ms. Erlang can spawn a new process every 10 ms, but if there is no reason why you cannot reuse the same process, it is usually not worth the overhead (although this is very small).
I would do something like this in OTP gen_server :
-module(periodic_task). ... module exports start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). ... Rest of API and other OTP callbacks init([]) -> Timer = erlang:send_after(0, self(), check), {ok, Timer}. handle_info(check, OldTimer) -> erlang:cancel_timer(OldTimer), Timer = erlang:send_after(10, self(), check), do_task(), % A function that executes your task {noreply, Timer}.
Then run gen_server as follows:
periodic_task:start_link().
As long as gen_server is working (if it works the same as the parent process, since they are connected), the do_task/0 function will execute almost every 10 milliseconds. Please note that this will not be entirely accurate. There will be a drift at run time. The actual interval will be 10 ms + the time required to receive the timer message, cancel the old timer and start a new one.
If you want to start a separate process every 10 ms, you can run the do_task/0 process. Please note that this will add extra overhead, but will not necessarily make the spawning interval less accurate.
My example was taken from this answer: What is the best way to do something periodically in Erlang?