- Structure every application as an OTP release with `rebar3 release` — define the release in `rebar.config` under `{relx, [...]}` with explicit application versions.
- Use `application:start(App)` or include the app in the release boot script — never start OTP applications with raw `spawn` or module calls.
- Use `sys.config` for environment-specific runtime configuration and `vm.args` for Erlang VM flags — never hardcode node names or cookie values in source.
- Use `rebar3 shell --apps myapp` to start the full OTP application in an interactive shell for REPL-driven development and debugging.
- Use `observer:start()` in development to inspect the process tree, ETS tables, and memory allocation in the running node.
- Use `release_handler` for hot code upgrades in production — write `.appup` files that define `up` and `down` instructions for each version transition.
- Use `mnesia` for distributed, in-memory storage that requires transactions; use ETS for local, high-throughput, non-transactional storage.