How pin codes are used, like passwords, are numerous and varied.
Sadly, there are still a lot of implementations that simply keep the pin/pass in clear text in a table (DB or Flat) correlated with the User ID.
Better, is a HASH of the pin/pass is kept correlated with the User ID. That way if the DB is compromised, they don't get clear pin/pass information. Thieves of the server table would need to break the hash, but widely available rainbow tables make that very viable.
Better-Still, is a HASH of the pin/pass + SALT. SALT is a random addition that eliminates the use of pre-computed hash/rainbow tables. Now a table thief has to spend time attempting a brute force attack. Note that with a small pin, this is quite viable as well.
Better-Still-More, is to add "round counts" of hashing the hash of the hash of the hash a few thousand to million times. This requires a thief to know the round count and if the count is large enough to require 2-3 seconds per attempt, brute force becomes even more difficult. Note that a small pin is still vulnerable.
The Bigger Concern and most common mistake made again and again is failure to prevent direct online brute force attacks. People make mistakes and need to be allowed multiple attempts, but a realistic limitation along the lines of say, 5 attempts within a 3 minute window, accounts for humans but hundreds of attempts at impossible typing speeds is an attack, don't allow that! The Linux utility "Fail2Ban" is handy for blocking these kinds of online attacks. Too many attempts within the window, block the IP for 30 minutes. A real person can wait it out to try again, but an automated high speed attack will generally give up and move on.