Model a system
System Context
Declare the system’s external dependencies, global SLAs, constraints, and data classification. This is the “why” behind the numbers in your model.
Syntax
Section titled “Syntax”system SystemName { external: service-name (role), service-name (role) slo: metric target, metric target region: region-list data-classification: classification constraint: description}Attributes (all optional, but at least one is recommended):
| Attribute | Values | Meaning |
|---|---|---|
external |
name (role) |
External services this system depends on |
slo |
metric target |
Global service-level objectives |
region |
comma-separated list | Geographic deployment regions |
data-classification |
pii, pci, phi, public, internal |
Data sensitivity level |
constraint |
free text | Hard constraints (e.g., “must run on-prem”, “GDPR compliant”) |
Examples
Section titled “Examples”system RateLimiterAPI { external: stripe (payment-gateway), sentry (monitoring) slo: 99.99% uptime, p99 < 2ms region: us-primary, eu-secondary data-classification: pii}
system PaymentProcessor { external: stripe (payment), paypal (payment), twilio (sms) slo: 99.95% uptime, p99 < 500ms region: us-east, us-west, eu-west data-classification: pci constraint: must support 3DSecure fallback}Why This Matters
Section titled “Why This Matters”System context turns arbitrary numbers into grounded decisions:
- External dependencies imply failure modes. If
stripeis down, what happens toprocessPayment? - SLOs drive architecture. 99.99% uptime means <44s downtime/month. That requires replication, failover, and health probes.
- Regions affect latency and data residency. A user in EU hitting a US-primary boundary has higher latency and potential GDPR issues.
- Data classification affects encryption, access control, and audit requirements.
Without a system context, @cost(writeRpsPeak=50000) appears in a vacuum. With it, the number is grounded in a system that promised 99.99% uptime and <2ms latency.
External Dependencies
Section titled “External Dependencies”Every external declaration is a potential failure point. When you list one, you should also model its failure mode:
system PaymentAPI { external: stripe (payment)}
// If Stripe is down:stripe-webhook-timeout { invoiceId } --[timeout > 5s]--> [ payment-deferred { invoiceId, reason: "stripe_unavailable" } ]If you declare an external dependency but never model its failure, that’s a gap.
SLOs and Boundaries
Section titled “SLOs and Boundaries”SLOs should map to specific boundaries:
system RateLimiterAPI { slo: 99.99% uptime, p99 < 2ms}
boundary UserRateLimit(userId, currentMinute) @ops(slo="99.99%", alert="rate-limit-shard-unavailable") @time(window="fixed:1m", clockSkewBudget="<250ms")The boundary’s @ops should reference the system’s SLO. If it doesn’t, ask: “Is this boundary covered by the global SLO, or does it need its own?”
Regions and Partitioning
Section titled “Regions and Partitioning”Regions affect partition strategy:
system GlobalAPI { region: us-primary, eu-secondary, ap-southeast}
boundary UserRateLimit(userId, currentMinute) @partition(shardKey="userId") @replication(mode="async", lagSla="<5s")Multi-region implies replication strategy. Async replication means some regions see stale data. Ask: “Is staleness acceptable for this boundary? What’s the user experience in EU while US primary is catching up?”
Data Classification
Section titled “Data Classification”Data classification affects encryption, access control, and retention:
system HealthRecords { data-classification: phi}
// PHI requires:// - Encryption at rest and in transit// - Audit logging on all access// - Retention policies (e.g., 7 years)// - Access limited to minimum necessaryIf you declare data-classification: pii or pci, your model should have corresponding guards, encryption annotations, or access controls. If it doesn’t, that’s a gap.
Anti-Patterns
Section titled “Anti-Patterns”❌ No System Context
Section titled “❌ No System Context”// Bad: numbers without contextboundary UserRateLimit(userId, currentMinute) @cost(writeRpsPeak=50000) @ops(slo="99.99%")Where did 50k come from? Why 99.99%? What external services does this touch?
❌ Context Without Consequences
Section titled “❌ Context Without Consequences”// Bad: declared external dependency, never referencedsystem PaymentAPI { external: stripe (payment)}
// ... 50 lines of DSL later, no mention of Stripe failure mode ...If you declare it, model it. Otherwise the declaration is noise.
In Interviews
Section titled “In Interviews”Open with the system context:
“Before I model the event flow, here’s the system context: this is a rate limiter API with 99.99% uptime and <2ms p99 latency, deployed in US-primary and EU-secondary. It depends on Stripe for payments and Sentry for monitoring. Data is PII.”
This gives the interviewer the constraints you’re working within, and it signals that you’re thinking about the full system, not just the happy path.