Cookies are sent to the server with every matching request and can expire; localStorage persists until cleared and stays in the browser; sessionStorage lasts for the current tab only.
Use a small, pinned base image, order instructions so dependencies are cached before source code, use multi-stage builds to leave build tools out of the final image, run as a non-root user and keep secrets out of the image.
Session authentication stores the login state on the server and gives the browser a session ID cookie, while JWT authentication gives the client a signed token that contains the user's claims so the server can verify it without storing state.
Choose an algorithm such as token bucket or sliding window, store a counter per client (by user ID, API key or IP) in a fast shared store like Redis, and return HTTP 429 with a Retry-After header when the limit is exceeded.
Validate all input, use parameterised queries, add security headers with helmet, rate-limit requests, restrict CORS, hash passwords, keep secrets in environment variables, and keep dependencies updated and audited.