GraphQL Enums â Fixed Value Sets for Type-Safe APIs
In this tutorial, you will learn about Graphql Enums. We cover key concepts, practical examples, and best practices to help you master this topic.
GraphQL enums define a fixed set of allowed values for a field, providing autocomplete, validation, and type safety that plain strings cannot match.
What You'll Learn
You will learn how to define enums in SDL, use them in types and arguments, handle enum values in resolvers, map enums to backend values, and design effective enum types.
Why Enums Matter
Strings are flexible but error-prone. A typo like "CRITCAL" instead of "CRITICAL" passes string validation but breaks logic downstream. Enums restrict fields to exact values â GraphQL validates at the API boundary and rejects invalid inputs automatically. DodaTech's Durga Antivirus Pro uses enums for Severity, DeviceStatus, ScanResult, ThreatType, and UserRole â eliminating an entire class of bugs caused by misspelled strings.
flowchart LR
A["SDL: enum Severity {\n LOW\n MEDIUM\n HIGH\n CRITICAL\n}"] --> B["Client sends:\nthreats(severity: CRITICAL)"]
B --> C["GraphQL validates\nagainst enum values"]
C -->|"Valid"| D["Resolver receives\nstring 'CRITICAL'"]
C -->|"Invalid"| E["GraphQL error:\n'CRITCAL' is not\na valid enum value"]
style A fill:#dbeafe,stroke:#2563eb
style C fill:#fef3c7,stroke:#d97706
style E fill:#fca5a5,stroke:#dc2626
Prerequisites: GraphQL SDL and basic resolver knowledge.
Defining Enums in SDL
enum Severity {
LOW
MEDIUM
HIGH
CRITICAL
}
enum DeviceStatus {
ONLINE
OFFLINE
QUARANTINED
DELETED
PENDING_UPDATE
}
enum ScanResult {
CLEAN
INFECTED
SUSPICIOUS
ERROR
SCANNING
}
Enum values must be uppercase by convention (UPPER_SNAKE_CASE) and must start with a letter or underscore.
Using Enums in Types and Arguments
type Threat {
id: ID!
name: String!
severity: Severity!
status: ThreatStatus!
detectedAt: DateTime!
}
type Query {
threats(severity: Severity): [Threat!]!
threatsBySeverity(severities: [Severity!]!): [Threat!]!
}
type Mutation {
updateThreatSeverity(id: ID!, newSeverity: Severity!): Threat!
}
# Queries using enum values
query CriticalThreats {
threats(severity: CRITICAL) {
id
name
detectedAt
}
}
query MultipleSeverities {
threatsBySeverity(severities: [HIGH, CRITICAL]) {
id
name
severity
}
}
# Expected response
{
"data": {
"threatsBySeverity": [
{ "id": "thr-001", "name": "Emotet", "severity": "CRITICAL" },
{ "id": "thr-002", "name": "Adware", "severity": "HIGH" }
]
}
}
Enum Resolvers and Internal Mapping
Sometimes your backend uses different values (integers, lowercase) than your GraphQL enum:
const resolvers = {
Severity: {
LOW: 1,
MEDIUM: 2,
HIGH: 3,
CRITICAL: 4,
},
ThreatStatus: {
ACTIVE: 'active',
RESOLVED: 'resolved',
FALSE_POSITIVE: 'false_positive',
},
Query: {
threats: (_, { severity }) => {
// severity is the enum string (e.g., "CRITICAL")
// Map to internal value if needed
const severityMap = { LOW: 1, MEDIUM: 2, HIGH: 3, CRITICAL: 4 };
const internalSeverity = severity ? severityMap[severity] : null;
return threats.filter(t =>
!internalSeverity || t.severityLevel >= internalSeverity
);
},
},
};
If your enum values match exactly between GraphQL and your backend, you don't need explicit enum resolvers â GraphQL uses the default resolver.
Enums vs String Unions
# Bad â string without validation
type Threat {
severity: String! # Accepts any string: "CRITICAL", "critical", "CRITCAL"
}
# Good â enum with validation
enum Severity { LOW MEDIUM HIGH CRITICAL }
type Threat {
severity: Severity! # Only these exact values accepted
}
Enums provide autocomplete in GraphiQL, schema validation, and type generation. String unions provide neither.
Enums with Descriptions
"Severity level of a detected threat"
enum Severity {
"Low priority â informational only"
LOW
"Medium priority â requires attention"
MEDIUM
"High priority â potential breach"
HIGH
"Critical priority â immediate action required"
CRITICAL
}
Descriptions appear in GraphiQL documentation, making the API self-documenting.
Common Mistakes
1. Using Strings Instead of Enums for Fixed Values
If a field can only be one of 3-5 values, it should be an enum. Strings accept any value, including typos and unexpected inputs.
2. Making Enums Too Granular
Separate enums for Severity, Priority, Urgency tend to have the same values. Use one enum per domain concept.
3. Changing Enum Values in Production
Removing an enum value is a breaking change â existing clients may send the removed value. Add new values only (backward-compatible).
4. Forgetting to Handle Enum Mapping in Resolvers
If your database stores severity as integers (1-4) but your enum uses string values, you must map between them in resolvers.
5. Not Documenting Enum Values
Without descriptions, developers must guess what each value means. Add descriptions for every enum value, especially non-obvious ones.
Practice Questions
- What naming convention should enum values follow?
- Can enum values have spaces or special characters?
- How do you map GraphQL enums to different backend values?
- Is removing an enum value a breaking change?
- What is the advantage of enums over String types?
Answers:
- UPPER_SNAKE_CASE by convention. Values must start with a letter or underscore and can contain alphanumeric characters and underscores.
- No â only letters, digits, and underscores. No spaces, hyphens, or special characters.
- Add a resolver for the enum type with key-value pairs mapping GraphQL values to backend values:
Severity: { LOW: 1, MEDIUM: 2, ... }. - Yes â existing clients may send the removed value in queries or variables. Only add new values, never remove or rename.
- Enums provide validation at the API boundary, autocomplete in GraphiQL, type generation for TypeScript, and documentation for each value.
Challenge: Design enums for DodaTech's full threat management system. Include enums for EventType (THREAT_DETECTED, SCAN_COMPLETED, DEVICE_STATUS_CHANGE), NotificationChannel (EMAIL, SMS, PUSH, Webhook), and AlertRuleOperator (GT, LT, EQ, CONTAINS, MATCHES). Add descriptions to all values and implement resolvers that map to internal codes.
FAQ
Mini Project
Create a GraphQL schema for DodaTech's alert routing system. Include enums for AlertChannel (EMAIL, SMS, PUSH, WEBHOOK, SLACK), AlertPriority (LOW, MEDIUM, HIGH, CRITICAL), AlertState (TRIGGERED, ACKNOWLEDGED, RESOLVED, SUPPRESSED). Add input types that use these enums and implement resolvers with internal mapping.
What's Next
| Topic | Description |
|---|---|
| Interfaces Guide | Shared fields across types |
| Union Types | Polymorphic return types |
| Schema Definition Language | SDL syntax fundamentals |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro