5Stack supports four tournament formats, each designed for different competitive scenarios. This guide covers how each format works, when to use them, and how they’re implemented.
Swiss Best for : Large tournaments (10-64 teams) with fair matchmakingDuration : 5-7 rounds typicalComplexity : Medium
Round Robin Best for : Small groups (4-16 teams) where everyone plays everyoneDuration : (N-1) rounds for N teamsComplexity : Low
Single Elimination Best for : Quick tournaments with clear progressionDuration : log2(N) roundsComplexity : Low
Double Elimination Best for : Fair competition with second chancesDuration : 2 * log2(N) roundsComplexity : High
Swiss is a non-elimination format where teams play until they reach a win or loss threshold. It’s ideal for large tournaments where you want fair matchmaking without eliminating teams.
How Swiss Works
Initial Matches
All teams start at 0-0. First round matches are created randomly or by seed.
Record-Based Pairing
After each round, teams are matched against others with similar records:
1-0 teams play 1-0 teams
0-1 teams play 0-1 teams
1-1 teams play 1-1 teams
Advancement/Elimination
Teams reaching 3 wins advance to the next stage. Teams reaching 3 losses are eliminated.
Continue Until Complete
Tournament continues until all teams have either advanced or been eliminated.
Swiss Match Types
Swiss tournaments have three types of matches:
Standard matches where teams haven’t reached advancement/elimination threshold. Example : 1-1 vs 1-1, 2-0 vs 2-0
Teams at 2-X playing for their 3rd win. Example : 2-0 vs 2-0, 2-1 vs 2-1, 2-2 vs 2-2Winner advances to next stage.
Teams at X-2 playing to avoid 3rd loss. Example : 0-2 vs 0-2, 1-2 vs 1-2, 2-2 vs 2-2Loser is eliminated from tournament.
Record Pool Structure
The Swiss bracket viewer groups matches by win-loss records:
interface RecordPool {
record : string ; // e.g., "2-1"
wins : number ;
losses : number ;
brackets : Bracket []; // Matches in this pool
advancedTeams : string []; // Teams that advanced from here
eliminatedTeams : string []; // Teams eliminated from here
}
Swiss Configuration
const swissStage = {
stage_type: 'Swiss' ,
groups: 1 ,
min_teams: 10 , // Minimum 10 teams (must be even)
max_teams: 64 , // Maximum 64 teams
default_best_of: 1 , // Default BO1 for regular matches
settings: {
round_best_of: {
'regular' : 1 , // Regular matches: BO1
'advancement' : 3 , // Advancement matches: BO3
'elimination' : 3 // Elimination matches: BO3
}
}
};
Swiss requires an even number of teams to ensure proper pairing. Odd team counts will result in errors.
Record Encoding
Swiss uses numeric group values to encode win-loss records:
// Group value encoding:
// If < 100: group = losses (e.g., 1 = 0-1, 2 = 0-2)
// If >= 100: wins * 100 + losses (e.g., 100 = 1-0, 201 = 2-1)
function parseGroupToRecord ( group : number ) : { wins : number ; losses : number } {
if ( group === 0 ) return { wins: 0 , losses: 0 };
if ( group < 100 ) return { wins: 0 , losses: group };
const wins = Math . floor ( group / 100 );
const losses = group % 100 ;
return { wins , losses };
}
When to Use Swiss
Use Swiss when:
You have 10-64 teams
You want fair matchmaking based on performance
You need to seed teams for a playoff stage
You want longer tournaments with many matches
Avoid Swiss when:
You have fewer than 10 teams
You need quick results
Teams expect single-elimination format
Round Robin is a format where every team plays every other team once. It’s perfect for small groups where you want complete standings.
How Round Robin Works
Generate All Matchups
System creates matches for every possible pairing:
4 teams = 6 matches
6 teams = 15 matches
8 teams = 28 matches
Play All Matches
Teams play all their scheduled matches. Order doesn’t matter.
Calculate Standings
Final standings determined by:
Match wins
Round differential (tiebreaker)
Head-to-head (tiebreaker)
Round Robin with Groups
You can split teams into multiple parallel round-robin groups:
const roundRobinStage = {
stage_type: 'RoundRobin' ,
groups: 4 , // 4 parallel groups
min_teams: 16 , // 4 teams per group minimum
max_teams: 16 , // 4 teams per group exactly
default_best_of: 1
};
Teams are distributed evenly across groups:
16 teams, 4 groups = 4 teams per group
Each group runs independently
Top teams from each group can advance
Round Robin Results
The results table tracks detailed statistics:
< template >
< Table >
< TableHeader >
< TableRow >
< TableHead > Team </ TableHead >
< TableHead > Games Played </ TableHead >
< TableHead > Wins </ TableHead >
< TableHead > Losses </ TableHead >
< TableHead > Rounds Won </ TableHead >
< TableHead > Rounds Lost </ TableHead >
< TableHead > Matches Remaining </ TableHead >
</ TableRow >
</ TableHeader >
< TableBody >
< TableRow v-for = " result in stage . results " >
< TableCell > {{ result . team . name }} </ TableCell >
< TableCell > {{ result . games_played }} </ TableCell >
< TableCell > {{ result . wins }} </ TableCell >
< TableCell > {{ result . losses }} </ TableCell >
< TableCell > {{ result . rounds_won }} </ TableCell >
< TableCell > {{ result . rounds_lost }} </ TableCell >
< TableCell > {{ result . matches_remaining }} </ TableCell >
</ TableRow >
</ TableBody >
</ Table >
</ template >
When to Use Round Robin
Use Round Robin when:
You have 4-16 teams total
You want complete standings
You’re running group stages
Time permits many matches
Avoid Round Robin when:
You have many teams (match count explodes)
You need quick tournament completion
Teams expect bracket-style progression
Single Elimination is a traditional bracket where teams are eliminated after one loss. It’s the fastest format and easiest to understand.
How Single Elimination Works
Generate Bracket
Teams are placed in a bracket sized to next power of 2:
5-8 teams = 8-team bracket
9-16 teams = 16-team bracket
17-32 teams = 32-team bracket
Byes are awarded to top seeds if needed.
Play Matches
Winners advance to next round, losers are eliminated.
Crown Champion
Final match determines tournament winner.
Round Structure
Rounds are calculated based on bracket size:
function calculateSERounds ( teamsPerGroup : number ) : RoundInfo [] {
const totalRounds = Math . max (
Math . ceil ( Math . log ( teamsPerGroup ) / Math . log ( 2 )),
1
);
const rounds : RoundInfo [] = [];
for ( let r = 1 ; r <= totalRounds ; r ++ ) {
const matchesInRound = Math . pow ( 2 , totalRounds - r );
rounds . push ({
key: `WB: ${ r } ` ,
label: getRoundLabel ( r , matchesInRound , true ),
path: 'WB' ,
round: r
});
}
return rounds ;
}
Round Labels
Single Elimination uses descriptive labels:
Round 1, 2, 3… : Early rounds
Quarterfinals : 4 teams remaining
Semifinals : 2 matches remaining
Grand Final : Championship match
Third Place Match
Optionally include a 3rd place decider match:
const singleElimStage = {
stage_type: 'SingleElimination' ,
groups: 1 ,
min_teams: 8 ,
max_teams: 16 ,
default_best_of: 3 ,
third_place_match: true ,
decider_best_of: 3 // Best-of for 3rd place match
};
Per-Round Configuration
Configure different best-of settings per round:
settings : {
round_best_of : {
'WB:1' : 1 , // Round 1: BO1
'WB:2' : 1 , // Quarterfinals: BO1
'WB:3' : 3 , // Semifinals: BO3
'WB:4' : 5 // Grand Final: BO5
}
}
When to Use Single Elimination
Use Single Elimination when:
You need fast tournament completion
Bracket format is preferred by players
You have any number of teams (2-256)
Simple progression is desired
Avoid Single Elimination when:
You want to give teams second chances
Fairness is prioritized over speed
Early upsets would be controversial
Double Elimination features both winners and losers brackets, giving teams a second chance before elimination. It’s the most complex but fairest bracket format.
How Double Elimination Works
Winners Bracket Start
All teams start in the winners bracket (upper bracket).
First Loss
Teams losing in winners bracket drop to losers bracket (lower bracket).
Losers Bracket
Teams in losers bracket play elimination matches. One more loss eliminates them.
Grand Final
Winners bracket champion faces losers bracket champion. Some formats give WB champion one-match advantage.
Bracket Structure
Double Elimination has three bracket components:
Winners Bracket (WB)
Losers Bracket (LB)
Grand Final (GF)
Upper bracket where all teams start. Winners advance, losers drop to LB. // WB rounds for 8 teams
rounds : [
{ key: 'WB:1' , label: 'Winners Round 1' , matches: 4 },
{ key: 'WB:2' , label: 'Winners Semifinals' , matches: 2 },
{ key: 'WB:3' , label: 'Winners Finals' , matches: 1 }
]
Lower bracket for teams with one loss. Losers are eliminated. // LB has 2*(WB_rounds - 1) rounds
rounds : [
{ key: 'LB:1' , label: 'Losers Round 1' , matches: 2 },
{ key: 'LB:2' , label: 'Losers Round 2' , matches: 2 },
{ key: 'LB:3' , label: 'Losers Round 3' , matches: 1 },
{ key: 'LB:4' , label: 'Losers Finals' , matches: 1 }
]
Final match between WB champion and LB champion. rounds : [
{ key: 'GF' , label: 'Grand Final' , matches: 1 }
]
Round Calculation
function calculateDERounds ( teamsPerGroup : number ) : RoundInfo [] {
const W = Math . pow ( 2 , Math . ceil ( Math . log ( teamsPerGroup ) / Math . log ( 2 )));
const wbRounds = Math . round ( Math . log ( W ) / Math . log ( 2 ));
const lbRounds = wbRounds <= 1 ? 0 : 2 * ( wbRounds - 1 );
const rounds : RoundInfo [] = [];
// Winners Bracket rounds
for ( let r = 1 ; r <= wbRounds ; r ++ ) {
rounds . push ({
key: `WB: ${ r } ` ,
label: getRoundLabel ( r , true , false ),
path: 'WB' ,
round: r
});
}
// Losers Bracket rounds
for ( let r = 1 ; r <= lbRounds ; r ++ ) {
rounds . push ({
key: `LB: ${ r } ` ,
label: getRoundLabel ( r , false , true ),
path: 'LB' ,
round: r
});
}
// Grand Final
if ( wbRounds > 0 ) {
rounds . push ({
key: 'GF' ,
label: { key: 'Grand Final' },
path: 'WB' ,
round: wbRounds + 1
});
}
return rounds ;
}
Bracket Connections
Double Elimination brackets have complex connections:
interface Bracket {
id : string ;
round : number ;
path : 'WB' | 'LB' ; // Winners or Losers bracket
parent_bracket ?: Bracket ; // Where winner goes
loser_bracket ?: Bracket ; // Where loser goes (WB only)
feeding_brackets ?: Bracket []; // Brackets feeding into this one
}
Configuration Example
const doubleElimStage = {
stage_type: 'DoubleElimination' ,
groups: 1 ,
min_teams: 8 ,
max_teams: 16 ,
default_best_of: 3 ,
settings: {
round_best_of: {
'WB:1' : 1 , // WB Round 1: BO1
'WB:2' : 3 , // WB Semifinals: BO3
'WB:3' : 3 , // WB Finals: BO3
'LB:1' : 1 , // LB Round 1: BO1
'LB:2' : 1 , // LB Round 2: BO1
'LB:3' : 3 , // LB Round 3: BO3
'LB:4' : 3 , // LB Finals: BO3
'GF' : 5 // Grand Final: BO5
}
}
};
Bracket Visualization
Double Elimination brackets display both WB and LB:
Winners Bracket : Displayed on top
Losers Bracket : Displayed below
Connection Lines : Show progression paths
White lines: Winner advancement
Red lines: Loser drops to LB
When to Use Double Elimination
Use Double Elimination when:
Fairness is top priority
You want to reward consistency
Teams expect second chances
You have time for more matches
Avoid Double Elimination when:
Bracket complexity would confuse players
Tournament duration is limited
Single-elim simplicity is preferred
Choose the right format based on your tournament goals:
By Team Count
By Duration
By Fairness
By Complexity
4-8 teams : Round Robin or Single Elimination
8-16 teams : Single/Double Elimination
16-32 teams : Swiss → Single/Double Elim
32+ teams : Swiss → Single Elim playoffs
Quickest : Single Elimination
Fast : Swiss (BO1 matches)
Medium : Double Elimination
Longest : Round Robin
Most Fair : Round Robin (everyone plays everyone)
Very Fair : Swiss (record-based matching)
Fair : Double Elimination (second chance)
Less Fair : Single Elimination (one loss out)
Simple : Single Elimination, Round Robin
Medium : Swiss
Complex : Double Elimination
Combine formats for optimal tournament structure:
Example: Large Tournament
// Stage 1: Swiss for seeding
{
stage_type : 'Swiss' ,
max_teams : 64 ,
default_best_of : 1 ,
settings : {
round_best_of : {
'regular' : 1 ,
'advancement' : 3 ,
'elimination' : 3
}
}
}
// Stage 2: Double Elim playoffs
{
stage_type : 'DoubleElimination' ,
max_teams : 16 , // Top 16 from Swiss
default_best_of : 3 ,
settings : {
round_best_of : {
'GF' : 5 // BO5 grand final
}
}
}
Example: Group Stage Tournament
// Stage 1: 4 Round Robin groups
{
stage_type : 'RoundRobin' ,
groups : 4 ,
max_teams : 16 , // 4 teams per group
default_best_of : 1
}
// Stage 2: Single Elim playoffs
{
stage_type : 'SingleElimination' ,
max_teams : 8 , // Top 2 from each group
default_best_of : 3 ,
third_place_match : true
}
Implementation Details
Bracket Generation
Brackets are generated automatically when tournament starts:
-- Called on tournament start
SELECT update_tournament_stages(tournament_id);
-- Generates brackets based on:
-- 1. Stage type
-- 2. Team count
-- 3. Team seeds
-- 4. Group configuration
Match Creation
Matches are created progressively as tournament advances:
Initial Matches : Created on tournament start
Subsequent Matches : Created when previous round completes
Bracket Updates : Automatic based on match results
Next Steps
Creating Tournaments Step-by-step tournament creation guide
Bracket Visualization Understanding bracket display and navigation
Managing Tournaments Team management and tournament administration
Match Scheduling Schedule and manage tournament matches