Skip to content

Custom Alias

Custom aliases give users control over their short code — but every user-provided input is an attack surface.

Validate early, check reserved words fast, check availability last.


What Custom Aliases Are

Instead of a system-generated code like a3kZ9m, the user can request a memorable alias: pastebin.com/my-config, pastebin.com/deploy-notes, pastebin.com/team-standup.

Custom aliases must be: - URL-safe - Unique (not already taken) - Not conflicting with system routes


Validation Flow

When a user provides a customAlias in the POST body, the app server runs three checks in order before accepting it:

1. Format validation (app server, no DB/Redis needed)
   - Base62 characters only (a-z, A-Z, 0-9)
   - Length: 1–8 characters
   - No spaces, hyphens, slashes, emoji, special chars
   → Fail: 400 Bad Request immediately

2. Reserved word check (Redis SET lookup — O(1))
   - Words like: admin, api, health, login, logout, static, assets, docs
   - These conflict with your own API routes and system paths
   → Fail: 400 "alias not available"

3. Availability check (Postgres lookup on short_code PK)
   - Does a paste already exist with this short_code?
   → Fail: 409 Conflict "alias already taken"
   → Pass: use it as short_code, skip Redis INCR counter

Checks are ordered cheapest-first. Format validation costs nothing — pure string check on the app server. Reserved word check hits Redis — sub-millisecond, no DB round-trip. Availability check hits Postgres — only runs if the alias passed the first two checks.


Reserved Words in Redis

The reserved words list lives in a Redis SET. On startup, app servers load the list from DB into Redis. Checks are O(1):

SISMEMBER reserved_words "admin"  → 1 (reserved, reject)
SISMEMBER reserved_words "my-cfg" → 0 (not reserved, continue)

The list is small (hundreds of words at most) and rarely changes. Backed by Postgres for persistence — if Redis restarts, the app server reloads the list from DB on startup.


Overlap Risk — Custom Alias vs Generated Codes

The Redis counter generates codes like 000001, 000002, a3kZ9m. A user could request a custom alias that happens to be a future counter value — for example, requesting 000042 as a custom alias.

Two scenarios:

Scenario A — Custom alias requested before counter reaches that value: User gets 000042 as their alias. Later, counter increments to 42 and tries to use 000042. The Postgres INSERT fails (unique constraint on short_code). App server retries with the next counter value. One retry, no data corruption.

Scenario B — Counter already issued 000042: The availability check (step 3) catches this — 000042 already exists in pastes. User gets 409 Conflict. They must choose a different alias.

The unique constraint on short_code is the safety net. It catches any overlap regardless of source. The system never silently overwrites an existing code.


Why Custom Aliases Don't Use the Redis Counter

When a custom alias is accepted, the app server uses it directly as the short_code — it does NOT call Redis INCR. The counter is only for system-generated codes. Custom aliases bypass the counter entirely and go straight to the Postgres INSERT.

This means the counter doesn't "know" about custom aliases. That's fine — the counter's job is generating unique codes for the system-generated path. The Postgres unique constraint handles the rest.


Interview framing

"Custom alias validation in three steps: format check (Base62, 1-8 chars) on app server, reserved word check against Redis SET, availability check against Postgres PK. Cheapest checks first. Reserved words block system paths like /admin and /api. Overlap between custom aliases and generated codes handled by Postgres unique constraint — INSERT fails, counter retries with next value. Custom aliases bypass the Redis counter entirely."