The Invisible Pillars of a Great System
“Users notice features. They remember performance.”
After defining what the system will do in the Functional Requirements, it's time to define how well it should do those things.
At this stage will will focus on Non-Functional Requirements (NFRs) – the characteristics that make the system reliable, fast, scalable, and user-friendly.
If functional requirements define behavior, non-functional requirements define experience.
Why Non-Functional Requirements Matter
When users open a newsletter or hit “Publish”, they don't think about the backend.
But if the system takes 10 seconds to load, and fails to send emails, or crashes under load – that's what they remember.
Non-functional requirements ensure:
- Consistency under pressure
- Trust through reliability
- Growth through scalability
In essence:
They turn a product that works into a product that lasts.
Categories of Non-Functional Requirements
Let's break them down one by one – with practical expectations for this Substack-like platform.
1 Scalability
Goal: Handle growth in users, posts, and emails without major redesign.
| Type | Description | Design Decision |
|---|---|---|
| Vertical Scaling | Increase resources on one server | Good for MVP phase |
| Horizontal Scaling | Add more servers or containers | Future-ready approach |
| Elastic Scaling | Auto-adjust resources based on traffic | Implement with AWS ECS / Kubernetes |
Example:
If 10,000 readers receive a newsletter at once, the system should queue and deliver all emails within 2-3 minutes, not hours.
2 Performance
Goal: Every request should feel instant, every page snappy.
| Metric | Target |
|---|---|
| API response time | < 200ms for standard queries |
| Page load time | < 2s for any reader view |
| Email send queue | < 1 min delay for queued messages |
Tech Enablers:
- CDN for caching static assets
- Redis for frequently accessed data
- Lazy loading images and analytics
3 Availability
Goal: The system should always be accessible.
| Metric | Target |
|---|---|
| Uptime | 99.9% (roughly <9 hrs downtime/year) |
| Recovery Time (RTO) | < 10 minutes |
| Recovery Point (RPO) | < 1 hour data loss |
Approach:
- Multi-zone deployment (AWS/GCP)
- Health checks and failover nodes
- Automated backups and snapshots
Analogy:
Even if one data center “sleeps,” the newsletter still goes out.
4 Reliability
Goal: The system should perform consistently, even under failure.
| Component | Reliability Measure |
|---|---|
| Email Delivery | Retry 3× before failure |
| Payments | Idempotent requests for Stripe webhooks |
| Data Storage | Replicated PostgreSQL cluster |
Tools:
- Retry queues
- Logging and alerting
- Database replication
Reliability = predictability. If a creator clicks “Publish,” it must publish.
5 Security
Goal: Protect users, data, and payments from unauthorized access.
| Concern | Implementation |
|---|---|
| Authentication | OAuth + JWT tokens |
| Data Encryption | HTTPS + AES-256 for sensitive fields |
| Passwords | Hashed (bcrypt) |
| Payments | PCI-compliant Stripe integration |
| Role Management | RBAC (Reader, Creator, Admin) |
| DDoS Protection | CDN-level rate limiting |
Creators own their data. The system just guards it.
6 Usability
Goal: The platform should feel effortless.
| Aspect | Example |
|---|---|
| Onboarding | 2-minute setup to publish first post |
| Editor | Clean markdown experience |
| Navigation | 3-click access to any dashboard view |
| Accessibility | WCAG 2.1 AA standards (keyboard + screen reader support) |
Principle:
If a user needs a tutorial to publish, I have failed the design.
7 Extensibility
Goal: Allow easy integration of new features, plugins, or themes wihout rewriting the core.
| Future Additions | Should Be Possible Without... |
|---|---|
| Plugin system | Touching core backend |
| Custom themes | Editing existing frontend code |
| External APIs | Rewriting routes or middleware |
Design Direction:
- Modular architecture
- Defined APIs between services
- Event-based communication
8 Maintainability
Goal: Developers (including future me) should easily extend and debug.
| Practice | Implementation |
|---|---|
| Code organization | Clean folder structure (services/modules) |
| Documentation | Inline + API docs |
| CI/CD | Automated tests before deploy |
| Error logging | Centralized log management |
| Monitoring | Dashboards for uptime and performance |
Maintainable code saves more time than fast code.
9 Portability
Goal: The system should run on any modern cloud or on-prem setup.
| Layer | Flexibility |
|---|---|
| Backend | Dockerized (runs anywhere) |
| Database | PostgreSQL (standard SQL) |
| Cloud Provider | AWS / GCP / DigitalOcean |
| Deployment | CI/CD pipelines portable via containers |
So if one cloud becomes costly, migration is simple – no vendor lock-in.
10 Observability
Goal: Know exactly what's happening at all times.
| Aspect | Example |
|---|---|
| Metrics | Response times, queue latency |
| Logging | Structured logs per request ID |
| Tracing | Request tracing across services |
| Alerts | Slack/email alerts on downtime |
Without observability, debugging at scale becomes blindfolded firefighting.
Leave a comment
Your email address will not be published. Required fields are marked *
