How are brew services different from launchctl services? On MacOS, how are brew services different from launchctl services? is there a way to use snap on a Mac to run services instead of brew?
Brew handles the complexity of parsing each package and then issues the appropriate launchctl commands for you. So in the end, launchctl and launchd do the lifting, brew just is an intermediary to make it easier for you to get going. 

% brew services -help



  Usage: brew services subcommand
  
  Manage background services with macOS' launchctl(1) daemon manager.
  
  If sudo is passed, operate on /Library/LaunchDaemons (started at
  boot). Otherwise, operate on ~/Library/LaunchAgents (started at
  login).


This is all covered well in the first 6 lines of the help and you can inspect the code in github if you are curious how this actually works behind the scenes.