We want to deliver value to the customer as fast as possible.
We can increase the delivery speed by focusing the team’s effort on getting single tasks from To Do to Done as fast as possible. In general we prefer finishing an already started task before picking up a new one. A ticket that is 80% finished has 0% value for the customer but costed 80% of the time. Having many of these half finished tickets on the board can quickly add up in cost.
Enter WIP limits.

Set the limit

In order to keep the focus we should limit the amount of work that can be in a single column. There is no fast and hard rule as to how high the limits should be set. In general in a team of n devs I’d like n+1 slots in In Progress. For the Review column I’d start with half that many slots. For Testing I would assign the same amount of slots as full-time QA engineers available for the project. If the QA engineer is split over multiple project don’t assign a full slot.

Keep focus

Everyone in the team should be working on one thing and one thing only. It is preferential to get a ticket that has finished development through review and testing to Done first before starting a new ticket. The WIP limits help with this by forcing people to pick up tickets in later columns before they can move a new ticket into the first column.
When development goes faster than reviewing tickets will start piling up in the In Progress column. If the problem is not addressed soon the devs won’t be able to drag tickets from To Do into In Progress because of the WIP limit. This forces them to look at tickets to review in order to make room in the In Progress column. Alternatively they can help another dev by pair programming on a particularly difficult ticket

Make bottlenecks visible

If there happens to be a problem in testing - maybe some tickets are proving very hard to test - and the review column is full then the devs are stuck. They can’t start new tickets and they can’t start reviewing since both columns are full. This may seem like an issue but it is fact making an underlying bottleneck visible.
The bottleneck at testing has now been made clear very early so the team is forced to stop and help out the testing team. Either by testing other tickets themselves or assist the QA engineer with testing the ticket they are stuck on.
Now if these limits were not in place tickets would simply pile up in the Ready For Validation state and no-one would be the wiser that the testing team is having issues. All they will see is an ever growing amount of tickets that they need to test before the end of the sprint, all whilst trying to figure out the issue they are having currently.

Represent the actual state

Without the limits in place the In Progress column is a misnomer. If we have 5 devs and 12 tickets in the In Progress column, how many tickets are actually being worked on? Who is actually working on which ticket?
If we have 2 testers with 8 tickets in Testing how many are actually being tested?
There is no easy way to get a clear overview of the current state of the project. In many cases it is better to know that the team is working on a couple of tickets even though they are not in the In Progress column. It is a clear indication that they are either doing reviews, helping with testing, doing some pair programming or fixing another bottleneck somewhere in the pipeline.
If we just allow people to keep dragging tickets into In Progress these problems haven’t suddenly vanished. They are just hidden and will come back at a later time.

Be flexible

Since every team is different and requirements and customer demands constantly change we need the flexibility to adapt these limits if they don’t work well. The team composition might change for many reasons, the scope may change, pragmatism may dictate to increase the limits, etc. In any case keep in mind the reasons for the limits before deciding on new ones.