Writing a pattern
Three characters in the pattern are placeholders and everything else is copied through exactly as typed.
| Character | Fills with | Bits, look-alikes removed |
|---|---|---|
| A | A letter | 4.52 |
| 9 | A digit | 3.00 |
| * | A letter or a digit | 4.95 |
| Anything else | Itself, unchanged | 0 |
So AAAA-9999 produces four letters, a literal hyphen and four digits, and is worth about 30 bits. The hyphen contributes nothing to the keyspace and a good deal to whether a human can read the code back without losing their place — group separators every four or five characters are the single cheapest readability improvement available, and they cost nothing but width. A fixed prefix behaves the same way: useful for sorting and for telling one campaign from another, worth zero bits, and known to anybody who has seen one code.
Keyspace, entropy and the guessing number
The keyspace is the product of the number of options at each random position. Entropy is its base-two logarithm, which is the more useful form because it adds: each extra letter position adds about 4.5 bits regardless of how long the code already was, and every 10 bits multiplies the space by roughly a thousand.
The number that actually matters operationally is neither of those. It is issued codes divided by possible codes, because that is the chance a single random guess lands on a live one. A hundred codes in a 30-bit space gives about one in ten million per attempt, which is comfortable. A hundred thousand codes in the same space gives one in ten thousand, which an automated script clears in minutes. The same pattern is fine in the first case and useless in the second, so the density is the thing to watch as a campaign grows — not the pattern that was chosen when it was small.
Uniqueness, and why the last few codes are the expensive ones
With duplicates switched off, each generated code is checked against the ones already made and redrawn if it collides. That works well while the batch is small relative to the keyspace and gets slow exactly as the batch approaches it, because near the end nearly every draw hits something already taken. The tool gives up and tells you rather than spinning, and the fix is always to widen the pattern rather than to keep trying.
Collisions arrive earlier than intuition suggests even far from that limit. Drawing n codes from a space of N produces about n²/2N duplicates, so ten thousand codes from a million-code space yields around fifty collisions — five in ten thousand, from a batch using one per cent of the space. It is the birthday problem again, and it is why uniqueness has to be enforced by checking rather than assumed from the size of the space.
What a code like this is and is not
A generated code is a reference: something to look up in a list you control. Whether it also functions as a secret depends entirely on the system behind it. A ticket code checked by a person against a printed list does not need to resist guessing at all. A discount code that anybody can try at checkout, repeatedly, with no penalty for a wrong answer, is being attacked by definition and the keyspace is the only thing standing in the way.
Two things help more than lengthening the pattern. Rate limit the redemption endpoint, so an attacker gets a handful of attempts a minute instead of thousands a second. And return the same response for a code that never existed and a code that exists but is already spent, since a system that distinguishes them tells the attacker when they are close and cuts the real cost of a search dramatically. If the value at stake is high, do not stretch a code into a credential — use a real one. The password generator and passphrase generator exist for that, and for an identifier that is never typed by hand, a UUID gives you 122 random bits and a standard format for free.
Questions people ask
How long should a code be?
That depends on how many you will issue and what a valid one is worth, and the results panel gives you both halves of the answer: the total keyspace, and the odds that a single guess hits one of the codes you actually issued. Pick a length that keeps those odds acceptable at the batch size you expect to reach, not the one you are starting with. A pattern chosen for a thousand codes will be uncomfortable at a million.
Why remove I, l, 1, O and 0?
Because codes get typed by people reading them off paper, a screen photograph or a phone call, and in most fonts a capital I, a lowercase l and a digit 1 are hard or impossible to tell apart, as are a capital O and a zero. Removing them costs about 0.35 bits per position and eliminates the most common transcription failure. If the code will only ever be copied and pasted, turn the option off and take the bits back.
Are the codes guaranteed unique?
Within a single batch, yes when the no-duplicates option is on — each code is checked against the ones already generated and redrawn on a collision. Across separate batches, no. This page keeps nothing between runs, so two batches from the same pattern can overlap. If uniqueness has to hold globally, the check belongs in the system that stores them: a unique constraint on the column is the only version of this guarantee that survives a page refresh.
Can I use these as passwords or API keys?
They come from the same cryptographic random source with the same unbiased reduction, so the randomness is not the problem — the length usually is. A typical coupon pattern carries around 30 bits, which is many orders of magnitude below what a credential wants. If you need a secret, generate a secret: the password generator and passphrase generator are built for that and print the entropy so you can compare directly.
Does the fixed prefix add any security?
None. It is identical in every code, so anybody who has seen one knows it, and it multiplies the keyspace by one. Its value is organisational: it groups a campaign, makes codes sortable, and lets support staff tell at a glance which batch a code came from. Include it for those reasons and read the entropy figure as describing the random positions only, which is what the tool reports.