Moderating user signup, usernames, and profile fields
Signup moderation is one of the highest-leverage places to clean up a product early, but it is also one of the easiest places to annoy real users if the rules are blunt. You need to catch abusive handles and profile content without turning registration into a punishment for ordinary people.
The usual signup problem is that several different surfaces need moderation at once: username, display name, bio, and sometimes an introductory post or profile text. Teams often treat all of that as one moderation problem. It is not. A handle is not the same thing as a bio, and a bio is not the same thing as a first post.
When products ignore that distinction, they usually end up with one of two bad outcomes. Either obviously bad handles slip through because the rules are too weak, or ordinary users hit avoidable false positives because a one-size-fits-all filter is trying to police everything the same way.
What to moderate separately
At minimum, smaller products should think about three different surfaces:
- Handles and usernames. Short, structured strings that users know will be checked — which means motivated bad actors will try to evade detection through intentional obfuscation. Character substitution is the most common form: digits replacing letters, symbols replacing vowels. Simple keyword matching fails here. You need normalisation and consonant-skeleton matching to catch what a literal string comparison would miss.
- Bios and display names. Longer than a handle but still a defined field rather than open content. Usually lower urgency individually, but these fields carry a higher likelihood of identity-targeted language during mass-signup events, when someone is deliberately trying to seed a platform with bad accounts. The thresholds you use here should be looser than for handles, but not as loose as general content.
- First posts and longer profile text. These should use the same thresholds as normal content moderation, not the tighter rules you apply to handles. They are free text, context-dependent, and subject to the same ambiguity as anything else a user writes. Applying handle-level strictness here will produce false positives at scale.
The practical consequence is that you need different rules for different fields, not a single pass that treats everything the same. Collapsing them together means either over-blocking ordinary users or under-blocking the accounts you actually care about catching.
Why handle moderation is different
A handle is not like other content. It appears next to every message a user sends, every reply they post, and every thread they participate in. A bad handle is persistent and visible in a way that a single bad message is not — one bad message gets removed; a bad handle stays until someone manually renames the account, which often happens only after it has already caused harm and attracted attention.
That asymmetry justifies applying stricter rules at handle creation time than you would during normal content moderation. It also justifies being less tolerant of borderline cases. If a handle scores just below the block threshold, you should not necessarily let it through. The cost of a borderline handle that you later have to forcibly rename — after users have seen it, after it has appeared in screenshots, after someone has filed a report — is considerably higher than the cost of asking someone to pick a different name at signup. One of those outcomes affects only the person registering. The other affects everyone who encountered it in the meantime.
A practical Aegis Core approach
Aegis Core provides two endpoints suited to this workflow, and they serve different purposes:
POST /v1/moderate/handlefor usernames and handles. This endpoint applies normalisation passes before checking — stripping common obfuscation patterns so that a substituted character does not let an obvious attempt slide through. You should use this for the account identifier specifically, because that is where obfuscation attempts are most likely.POST /v1/moderate/structuredfor fields likebio,display_name, andpost_bodyin a single request. This returns per-field results, which matters: rather than a single pass/fail for the whole signup form, you get back exactly which field caused an issue. That lets you tell the user something useful, rather than issuing a generic rejection and leaving them to guess what went wrong.
Use handle moderation for the actual account identifier. Use structured moderation for the rest of the signup payload. The separation is not just a convenience — it ensures each field is being evaluated against the rules appropriate to what it is.
What to show the user
If a handle is rejected, a message that says "that username is unavailable" is not helpful and is arguably misleading. It implies the name is taken. If the name was rejected for moderation rather than availability, the message should reflect that — something like "that username is not allowed" is sufficient. You do not need to explain why, and you certainly should not explain what the moderation system found. But the distinction between "taken" and "not allowed" matters, both to the user who is registering in good faith and to your support team who will otherwise receive confusion tickets from people trying variations of a name that will never be available.
For bios and profile text, the right response depends on whether the result is a block or a review. If the content was blocked outright, treat it the same as a handle rejection — tell the user that content is not allowed. If it scored into review rather than block, the better approach in most products is to let the signup proceed and hold the bio for review. Blocking an entire registration because a bio scored ambiguously is a significant overreaction. The account is not live with harmful content — it is live with content that a human will check. That is an acceptable outcome.
Ban evasion at signup
People who have been banned will attempt to re-register. This is common enough that it is worth thinking about explicitly, even if you address it only partially. The usual signals are: disposable or low-reputation email domains, IP addresses or subnets that overlap with a previously banned account, and usernames that closely resemble a banned account's handle — same structure, slightly different spelling.
Handle moderation through AegisCore will catch fresh bad content, but it does not do ban evasion matching by itself. That is a product layer concern — it requires cross-referencing against your own ban list, which only you have. The right approach is to run both in combination: AegisCore catches new bad content that has not been seen before, and your own identifier checks catch someone who has already been banned trying to come back under a slightly different name. Neither check replaces the other.
What to do with the result
A sensible early workflow is:
- Block obviously unsafe handles or profile text immediately, before any account is created.
- Allow clearly safe content and complete the registration normally.
- For borderline profile content — bios and display names that score into review — let the signup proceed and route the content for human review. Do not block the registration.
Not every signup field needs a full review path. In most products, a review queue for handles is overkill — either the handle is fine or it is not, and the cost of holding registration open while a human reviews a username is not worth it. But bios, profile descriptions, and introductory posts are different. Those carry enough ambiguity that a review path makes sense, and the cost of letting a borderline bio through pending review is much lower than rejecting a registration that turns out to have been legitimate.
A concrete example
Consider a user who submits the username "n1gg3r_killer_88", a display name of "White Power", and a bio that says "DM me for the group". Run that through handle moderation and the handle fails immediately — the normalisation pass reconstructs the substituted characters and the result is a clear block. The display name fails immediately through structured moderation. The bio on its own would score low — it is three words that could mean almost anything out of context.
The important thing here is that you are seeing all three fields at the same time. The bio that looks harmless in isolation is obviously not harmless next to that handle and display name. That is an advantage signup moderation gives you that ongoing content moderation does not. When someone posts a message, you see that message. When someone registers, you see the whole picture at once — and you can act on it before any of that is visible to other users.
A single bad post can be removed. An account that got through signup moderation has already established itself and will continue to create work until it is caught and banned. Stopping it at registration costs nothing in terms of user experience. The person who constructed that signup form knew exactly what they were doing.
Avoiding wrongful blocks matters as much as catching bad accounts. Over-aggressive signup filtering teaches real users that your product is difficult to join, creates support load, and produces false confidence — because a team that believes it has an aggressive filter tends to be less vigilant downstream. Calibrate by surface, use the right endpoint for each field, and route uncertain cases to review rather than using uncertainty as a reason to block. That is the balance that actually works in practice.