DEV Community

amir taherkhani
amir taherkhani

Posted on

The Backend Engineering Evaluation Framework

How to Evaluate Any Backend Feature, Protocol, Pattern, or Architecture Decision

A backend feature is not production-ready just because it works.

It is production-ready when it has been evaluated from every important engineering perspective.


πŸ€” Why This Framework Exists

Backend engineers make important technical decisions every day:

  • Should we use REST or gRPC?
  • Should communication be synchronous or asynchronous?
  • Should we use Kafka, NATS, RabbitMQ, or HTTP?
  • Should this feature become a separate microservice?
  • Should we introduce a cache?
  • Should we use WebSocket, SSE, polling, or webhooks?
  • Can the system scale horizontally?
  • Can the team maintain this solution in two years?
  • What happens when a dependency becomes unavailable?
  • Can the system recover without losing data?

These decisions are often based on:

  • personal experience,
  • team preferences,
  • framework popularity,
  • online comparisons,
  • previous projects,
  • or trial and error.

Experience is valuable, but without a shared evaluation method, similar problems may receive completely different solutions.

This framework provides a reusable and structured way to evaluate backend engineering decisions.


🎯 What Can Be Evaluated?

Use this framework when selecting, designing, or implementing:

  • a backend feature,
  • a communication protocol,
  • a design pattern,
  • a microservice pattern,
  • service-to-service communication,
  • client-to-server communication,
  • an API,
  • a message broker,
  • a database,
  • a cache,
  • an external service,
  • a background worker,
  • an event-driven workflow,
  • a distributed system,
  • or an infrastructure integration.

It is framework-independent and applies to:

  • Go,
  • Java,
  • Rust,
  • C#,
  • Python,
  • JavaScript,
  • TypeScript,
  • NestJS,
  • Spring Boot,
  • ASP.NET,
  • Django,
  • FastAPI,
  • Express,
  • Laravel,
  • and other backend technologies.

🧠 Think Beyond β€œDoes It Work?”

Many teams ask only one question:

Does it work?

That is important, but it is only the beginning.

A professional engineering review should also ask:

  • Does it work correctly?
  • Is it simple?
  • Is it secure?
  • Can it scale?
  • Can another engineer understand it?
  • Can it be tested?
  • Can it be deployed safely?
  • Can it be monitored?
  • Can it survive failures?
  • Can it recover after an incident?
  • Is it worth the operational cost?

Each question represents a different quality property.

Together, these properties provide a complete picture of software quality.


🧭 The Four Evaluation Perspectives

A backend solution should be evaluated from four main perspectives:

  1. Business correctness
  2. Code and architecture quality
  3. Runtime and production quality
  4. Delivery and operational quality

This prevents teams from focusing only on code quality while ignoring production behavior, operations, cost, and business outcomes.


πŸ—οΈ The Engineering Lifecycle

Every backend feature goes through a lifecycle:

πŸ’‘ Idea
   ↓
πŸ›οΈ Architecture
   ↓
πŸ“ Design
   ↓
πŸ’» Implementation
   ↓
πŸ§ͺ Testing
   ↓
πŸš€ Deployment
   ↓
🌍 Production
   ↓
πŸ”„ Maintenance
Enter fullscreen mode Exit fullscreen mode

Different questions must be answered at each stage.

This framework therefore evaluates a solution:

  1. Before implementation
  2. During implementation
  3. At the end of implementation
  4. During testing
  5. In production

⭐ The Core Quality Properties

Property Main Question
βœ… Correctness Does it work correctly?
🎯 Responsibility Does each component have a clear purpose?
πŸ“– Readability Can developers easily understand it?
✨ Simplicity Is this the simplest sufficient solution?
πŸ”§ Maintainability Can it be changed and supported easily?
🧩 Modularity Is it divided into clear and independent modules?
🀝 Cohesion Are related responsibilities kept together?
πŸ”— Coupling Are dependencies minimized and controlled?
🌱 Extensibility Can new behavior be added safely?
πŸ§ͺ Testability Can the behavior be verified easily?
⚑ Performance Is it fast and resource-efficient?
πŸ“ˆ Scalability Can it handle increasing workload?
🌐 Availability Is it accessible when users need it?
πŸ›‘οΈ Reliability Can it work consistently over time?
πŸ’ͺ Resilience Can it survive and recover from failures?
πŸ”’ Security Is it protected against threats and misuse?
πŸ—„οΈ Data Integrity Does it preserve correct and consistent data?
πŸ”„ Compatibility Can it work with existing systems and clients?
🌍 Portability Can it run in different environments?
πŸ‘€ Observability Can we understand its internal behavior?
βš™οΈ Operability Can it be operated efficiently in production?
πŸš€ Deployability Can it be released safely?
♻️ Recoverability Can normal operation and data be restored?
πŸ’° Cost Efficiency Does it provide enough value for its cost?
πŸ“š Documentation Quality Can others understand, operate, and maintain it?

πŸ“Š Quality Properties Are Not Metrics

A quality property describes what we care about.

A metric tells us how to measure it.

For example:

Performance
β†’ p50 latency
β†’ p95 latency
β†’ p99 latency
β†’ throughput
β†’ CPU usage
β†’ memory usage
Enter fullscreen mode Exit fullscreen mode
Scalability
β†’ throughput per replica
β†’ scaling efficiency
β†’ saturation point
β†’ queue backlog growth
β†’ database connection pressure
Enter fullscreen mode Exit fullscreen mode
Reliability
β†’ success rate
β†’ availability
β†’ timeout rate
β†’ MTTR
β†’ error-budget consumption
Enter fullscreen mode Exit fullscreen mode

Avoid vague statements such as:

The service is fast.

Prefer measurable statements:

The service maintains a p95 latency below 200 ms at 2,000 requests per second.

The correct engineering flow is:

Quality Property
        ↓
Metric
        ↓
Target
        ↓
Verification Method
Enter fullscreen mode Exit fullscreen mode

1. πŸ“ Before Implementation

Before writing code, determine whether the proposed solution is appropriate for the problem.


1.1 Business Requirements

Ask:

  • What problem does the solution address?
  • Who uses it?
  • What is the expected result?
  • What business value does it provide?
  • Is real-time communication required?
  • Is synchronous processing required?
  • Can processing be asynchronous?
  • What happens if the operation fails?
  • Is eventual consistency acceptable?
  • What level of data loss is acceptable?

Technology should be selected after understanding the business problem.


1.2 Functional Requirements

Define:

  • required operations,
  • input formats,
  • output formats,
  • business rules,
  • validation rules,
  • error cases,
  • state transitions,
  • authorization rules,
  • data consistency requirements,
  • transaction requirements,
  • ordering requirements,
  • and idempotency requirements.

A feature should not begin implementation while its expected behavior is still ambiguous.


1.3 Workload Characteristics

Estimate:

  • expected number of users,
  • expected requests per second,
  • expected concurrent connections,
  • message frequency,
  • average payload size,
  • maximum payload size,
  • read/write ratio,
  • peak traffic,
  • traffic growth,
  • geographic distribution,
  • and long-running operation count.

A protocol suitable for 100 requests per second may not be suitable for 100,000.


1.4 Communication Requirements

Determine whether the communication is:

  • client-to-server,
  • service-to-service,
  • request-response,
  • event-driven,
  • synchronous,
  • asynchronous,
  • one-to-one,
  • one-to-many,
  • many-to-many,
  • unidirectional,
  • bidirectional,
  • real-time,
  • delayed,
  • streaming,
  • or message-based.

Also define:

  • message ordering,
  • retry behavior,
  • timeout behavior,
  • offline-client support,
  • and delivery guarantees.

Possible delivery guarantees include:

  • at-most-once,
  • at-least-once,
  • and effectively-once processing.

In practice, effectively-once behavior is usually achieved through idempotency and deduplication.


1.5 Protocol Suitability

Possible communication technologies include:

  • HTTP/REST,
  • gRPC,
  • GraphQL,
  • WebSocket,
  • Server-Sent Events,
  • Webhooks,
  • message queues,
  • event streaming,
  • MQTT,
  • NATS,
  • Kafka,
  • and AMQP.

Evaluate each candidate based on:

  • latency,
  • throughput,
  • payload efficiency,
  • streaming support,
  • bidirectional communication,
  • browser support,
  • language support,
  • load-balancer compatibility,
  • proxy compatibility,
  • connection management,
  • message ordering,
  • delivery guarantees,
  • backpressure support,
  • versioning support,
  • and operational complexity.

Do not select a protocol only because it is popular.


1.6 Architecture Suitability

Ask:

  • Does the solution fit the current architecture?
  • Is a new microservice actually required?
  • Could the feature remain inside an existing service?
  • Is the selected pattern solving a real problem?
  • Does it introduce unnecessary complexity?
  • Are service boundaries clear?
  • Is data ownership clear?
  • Is deployment ownership clear?
  • Are dependencies clear?
  • Can the solution evolve without major rewrites?

A new service adds more than code.

It also adds:

  • deployment,
  • monitoring,
  • networking,
  • security,
  • ownership,
  • failure modes,
  • versioning,
  • and operational overhead.

1.7 Security Requirements

Define:

  • authentication,
  • authorization,
  • service identity,
  • transport encryption,
  • data encryption,
  • secret management,
  • input validation,
  • rate limiting,
  • replay protection,
  • message integrity,
  • audit logging,
  • tenant isolation,
  • sensitive-data handling,
  • and compliance requirements.

Security should be designed before implementation, not added at the end.


1.8 Reliability Requirements

Define:

  • required availability,
  • maximum acceptable downtime,
  • maximum acceptable data loss,
  • retry strategy,
  • timeout strategy,
  • circuit breaking,
  • fallback behavior,
  • failure isolation,
  • duplicate-message handling,
  • dead-letter handling,
  • disaster recovery,
  • backup and restore,
  • recovery time objective,
  • and recovery point objective.

Recovery Time Objective

How quickly must the system recover?

Recovery Point Objective

How much data loss is acceptable?


1.9 Operational Requirements

Consider:

  • deployment model,
  • Kubernetes compatibility,
  • horizontal scaling,
  • load balancing,
  • service discovery,
  • configuration management,
  • monitoring,
  • logging,
  • distributed tracing,
  • alerting,
  • health checks,
  • graceful shutdown,
  • and rollback strategy.

A design that performs well but cannot be operated safely is not production-ready.


1.10 Cost and Complexity

Estimate:

  • development cost,
  • infrastructure cost,
  • operational cost,
  • licensing cost,
  • network cost,
  • storage cost,
  • observability cost,
  • required team expertise,
  • maintenance effort,
  • vendor lock-in,
  • migration cost,
  • and failure-recovery cost.

The most advanced solution is not always the best solution.


2. πŸ’» During Implementation

During implementation, evaluate the quality of the internal design and code.


2.1 Functional Correctness

Question: Does the feature solve the correct problem?

Check:

Metric Question
Requirement coverage Are all acceptance criteria implemented?
Business-rule correctness Are domain rules enforced in every path?
Input correctness Are valid and invalid inputs handled?
Output correctness Does the API return the expected result?
Boundary correctness Are minimum, maximum, empty, and null cases handled?
State-transition correctness Are only valid transitions allowed?
Data consistency Can partial updates occur?
Idempotency Can retries create duplicate effects?
Time correctness Are timezone and expiry rules correct?
Concurrency correctness Can simultaneous requests break invariants?

Example

For:

POST /orders/:id/pay
Enter fullscreen mode Exit fullscreen mode

Correctness means more than returning 200.

It also means:

  • an already-paid order is not charged twice,
  • a cancelled order cannot be paid,
  • retries are idempotent,
  • payment and order state remain consistent,
  • concurrent requests do not create duplicate payments,
  • currency and amount match the order.

2.2 Responsibility and Cohesion

Question: Does each component have one clear purpose?

Ask:

  • Does each class, module, method, and service have one clear responsibility?
  • Does the implementation belong in this module?
  • Is domain logic placed inside controllers or repositories?
  • Does one service coordinate too many unrelated operations?
  • Can the responsibility be described in one sentence?
  • Do methods operate on closely related behavior?
  • Is cross-cutting logic duplicated?

Useful indicators:

Metric Desired Direction
Responsibilities per class Low
Reasons to change One dominant reason
Cohesion High
Unrelated dependencies Low
Public methods per service Small and focused
Controller business logic Near zero
Cross-module knowledge Low

Poor:

@Injectable()
export class OrdersService {
  createOrder() {}
  sendEmail() {}
  generatePdf() {}
  chargeCreditCard() {}
  updateInventory() {}
  calculateAnalytics() {}
}
Enter fullscreen mode Exit fullscreen mode

Better:

OrdersApplicationService
β”œβ”€β”€ OrderRepository
β”œβ”€β”€ PaymentPort
β”œβ”€β”€ InventoryPort
β”œβ”€β”€ NotificationPort
└── DomainEventPublisher
Enter fullscreen mode Exit fullscreen mode

The application service coordinates the use case while specialized components own their responsibilities.


2.3 Readability

Question: Can developers easily understand it?

Check:

  • names clearly describe intent,
  • methods are small and focused,
  • control flow is easy to follow,
  • nesting is limited,
  • business terminology is consistent,
  • magic values are avoided,
  • comments explain decisions rather than syntax,
  • and errors clearly describe failures.

Useful review triggers:

Measurement Review Trigger
Function length More than 30–50 lines
Parameters More than 4–5
Nesting depth More than 3 levels
Cyclomatic complexity More than 10
Boolean parameters More than 1–2
Public methods per class More than roughly 7–10
File size More than roughly 300–500 lines

These numbers are heuristics, not absolute rules.

A cohesive 60-line algorithm may be clearer than six artificially fragmented methods.


2.4 Maintainability

Question: Can it be changed safely?

Maintainability includes:

Modularity

  • Can the feature change without editing unrelated modules?
  • Are domain, application, transport, and infrastructure concerns separated?
  • Are internal details hidden behind stable contracts?

Reusability

  • Are genuinely reusable rules extracted?
  • Is the abstraction reusable without feature-specific hacks?
  • Is duplicated behavior centralized correctly?

Analyzability

  • Can an engineer quickly find where a rule is implemented?
  • Are logs, traces, and naming sufficient for diagnosis?
  • Is data flow understandable?

Modifiability

  • How many modules must change for a normal requirement change?
  • Are extension points explicit?
  • Are condition chains growing for each new type?

Testability

  • Can domain behavior be tested without starting the full application?
  • Can dependencies be replaced?
  • Are time, randomness, and external services injectable?

Useful indicators:

Metric Preferred Direction
Change failure rate Lower
Files changed per feature Controlled
Regression rate Lower
Duplicate-code ratio Lower
Technical-debt ratio Lower
Time to understand feature Lower
Time to implement a change Lower
Test setup complexity Lower
Module instability Controlled
Repeated code churn Investigated

2.5 Modularity

Question: Is the system divided into clear modules?

Check:

  • modules have clear boundaries,
  • internal details are private,
  • circular dependencies are avoided,
  • cross-module imports are controlled,
  • each service owns its data and behavior,
  • and shared libraries contain only genuinely shared concepts.

Good modularity allows parts of the system to evolve independently.


2.6 Coupling

Question: Are dependencies minimized and intentional?

Inspect:

  • module coupling,
  • database-schema coupling,
  • framework coupling,
  • external-service coupling,
  • temporal coupling,
  • deployment coupling,
  • shared-state coupling,
  • event-contract coupling,
  • data-format coupling,
  • and test coupling.

Useful metrics:

Metric Meaning
Fan-in Number of components depending on this component
Fan-out Number of dependencies used by this component
Afferent coupling Incoming dependencies
Efferent coupling Outgoing dependencies
Instability Ce / (Ca + Ce)
Circular dependency count Architectural warning
Cross-module imports Boundary leakage
Shared mutable state Runtime coupling risk
Synchronous dependency depth Failure propagation risk

Ask:

  • Does the domain layer import framework-specific classes?
  • Can one external service block the whole request?
  • Does changing a database model break public contracts?
  • Are modules importing each other in both directions?
  • Are persistence entities exposed directly?

2.7 Simplicity

Question: Is this the simplest sufficient solution?

Check:

  • unnecessary abstractions are avoided,
  • unnecessary services are avoided,
  • unnecessary infrastructure is avoided,
  • design patterns solve real problems,
  • distributed processing is introduced only when justified,
  • and a microservice is not created where a module would be enough.

Useful indicators:

  • number of abstractions,
  • number of layers,
  • number of deployment units,
  • number of dependencies,
  • configuration-key count,
  • end-to-end call depth,
  • number of states,
  • number of failure modes.

Simplicity means avoiding complexity that provides no real value.


2.8 Extensibility

Question: Can new behavior be added safely?

Check:

  • new providers can be added with minimal modification,
  • new message types can be supported safely,
  • new protocols can be introduced through adapters,
  • new business rules do not require a rewrite,
  • extension points are explicit,
  • and public contracts remain stable.

Useful metrics:

Metric Question
Modification points How many existing files must change?
Extension points Can behavior be added through interfaces?
Conditional growth Does every type add another if?
Contract stability How often do public interfaces break?
Backward compatibility Can old clients continue working?
Migration complexity Can changes roll out incrementally?

Avoid premature abstractions.

Design for expected change, not every imaginary future scenario.


2.9 API and Contract Quality

Question: Is the public contract clear and stable?

Check:

  • resource names are clear,
  • HTTP methods have correct semantics,
  • status codes are consistent,
  • request and response schemas are explicit,
  • validation errors are machine-readable,
  • pagination and filtering are standardized,
  • date, money, enum, ID, and null behavior are defined,
  • and persistence entities are not exposed directly.

Compatibility checks:

  • additive changes are preferred,
  • deprecated fields have a migration period,
  • API and event schemas are versioned,
  • consumers tolerate unknown fields,
  • and old and new versions can coexist.

Useful metrics:

Metric Target
Breaking changes Zero without versioning
Contract-test coverage High
Undocumented endpoints Zero
Inconsistent error shapes Zero
Duplicate endpoint semantics Zero
Deprecated API usage Decreasing
Payload size Bounded

2.10 Performance

Question: Is it fast and resource-efficient?

Review:

  • algorithm complexity,
  • database query count,
  • query execution time,
  • indexes,
  • network call count,
  • external-service latency,
  • serialization cost,
  • payload size,
  • memory consumption,
  • CPU consumption,
  • connection usage,
  • cache usage,
  • batch-processing opportunities,
  • event-loop blocking,
  • thread usage,
  • and worker usage.

Runtime metrics:

Metric Description
p50 latency Typical request latency
p95 latency Slow-user experience
p99 latency Tail latency
Throughput Requests or messages per second
CPU usage Compute pressure
Memory usage Heap or process pressure
Event-loop lag Node.js responsiveness
GC pause duration Garbage-collection impact
Database query count Potential N+1 behavior
Query latency Database processing time
Connection-pool usage Database saturation
External-call latency Dependency contribution
Payload size Network and serialization cost
Cache hit ratio Cache effectiveness
Queue wait time Async-processing delay

Review questions:

  • Is there an N+1 query?
  • Is an unbounded dataset loaded into memory?
  • Are independent calls executed sequentially?
  • Is CPU-heavy work blocking requests?
  • Are unnecessary external calls made?
  • Is pagination mandatory?
  • Are indexes aligned with query patterns?
  • Is caching actually justified?
  • Does cache invalidation preserve correctness?
  • Is backpressure available?

2.11 Scalability

Question: Can it handle increasing workload?

Performance asks:

How fast does one instance handle the workload?

Scalability asks:

How does the system behave as workload and resources increase?

Scalability dimensions include:

  • horizontal scaling,
  • vertical scaling,
  • database scaling,
  • worker scaling,
  • queue scaling,
  • storage scaling,
  • geographic scaling,
  • tenant scaling,
  • and data-volume scaling.

Useful metrics:

Metric Description
Throughput per instance Instance efficiency
Scaling efficiency Gain per added instance
Maximum sustainable throughput Capacity before instability
Saturation point When latency and errors increase
Stateful-session dependency Scaling obstacle
Hot partition rate Uneven load
Database lock contention Write scaling limitation
Connections per instance Database scaling pressure
Queue backlog growth Worker capacity problem
Autoscaling reaction time Capacity response delay
Cold-start time New replica readiness
Shared-resource bottlenecks Centralized limits

Ask:

  • Is the application stateless?
  • Can multiple replicas process requests safely?
  • Are locks local to one process?
  • Is session state stored in memory?
  • Do scheduled jobs run once or once per replica?
  • Does each instance open too many connections?
  • Can jobs be distributed safely?
  • Can events be partitioned?
  • Are workloads uneven?
  • What becomes the first bottleneck at 10Γ— traffic?

2.12 Reliability and Resilience

Questions:

  • Can it work consistently?
  • Can it survive failures?

Useful metrics:

Metric Meaning
Availability Percentage of service time available
Success rate Correct operations divided by attempts
Error rate Failed operations divided by attempts
SLO compliance Reliability objective achievement
Error-budget consumption Reliability loss
MTBF Mean time between failures
MTTR Mean time to recovery
Retry success rate Retry effectiveness
Timeout rate Dependency or capacity issue
Circuit-breaker open rate Downstream instability
Dead-letter count Permanently failed messages
Duplicate-processing rate Idempotency issue
Recovery-point objective Maximum acceptable data loss
Recovery-time objective Maximum acceptable recovery time

Resilience checks:

  • every external call has a timeout,
  • retries are bounded,
  • backoff and jitter are used,
  • only safe operations are retried,
  • retryable operations are idempotent,
  • circuit breaking is considered,
  • bulkheads limit failure propagation,
  • partial failure is handled,
  • duplicate messages are handled,
  • failed messages have a recovery strategy,
  • graceful shutdown works,
  • readiness checks reflect reality,
  • and load shedding exists where necessary.

Retries without limits can amplify outages.


2.13 Security

Question: Is the system protected?

Review:

Authentication

  • Is identity verified correctly?
  • Are signature, issuer, audience, and expiry validated?
  • Is token revocation needed?
  • Are credentials stored safely?

Authorization

  • Is access checked server-side?
  • Is object-level authorization enforced?
  • Are policies more appropriate than simple roles?
  • Can users access another tenant’s data?

Input Protection

  • Are inputs validated?
  • Are unknown fields rejected where appropriate?
  • Are queries parameterized?
  • Are paths, URLs, templates, and commands protected?
  • Is mass assignment prevented?

Data Protection

  • Is sensitive data encrypted?
  • Are secrets excluded from source control?
  • Are sensitive values removed from logs?
  • Is personal data minimized?
  • Are retention and deletion rules defined?

Abuse Resistance

  • rate limiting,
  • payload-size limits,
  • pagination limits,
  • login throttling,
  • replay protection,
  • enumeration prevention,
  • idempotency-key validation,
  • and resource-exhaustion protection.

Useful metrics:

Metric Target
Critical vulnerabilities Zero before release
Known vulnerable dependencies Zero without exception
Exposed secrets Zero
Authorization test failures Zero
Security-control coverage Risk-based
Time to remediate Within SLA
Security regressions Decreasing
Audit-log coverage Complete for sensitive actions

2.14 Data Integrity and Consistency

Question: Is the data always correct?

Check:

  • database constraints enforce invariants,
  • transaction boundaries are correct,
  • partial writes are prevented,
  • isolation levels are appropriate,
  • lost updates are prevented,
  • unique constraints are used,
  • money uses correct numeric types,
  • timestamps and timezones are consistent,
  • migrations are backward compatible,
  • event publication is coordinated with state changes,
  • eventual consistency is documented,
  • and reconciliation is possible.

Useful metrics:

Metric Description
Constraint-violation rate Invalid write attempts
Duplicate-record rate Missing uniqueness
Reconciliation discrepancy rate Cross-system inconsistency
Transaction rollback rate Business or infrastructure failures
Deadlock rate Concurrency problem
Replication lag Read-consistency risk
Stale-read rate Eventual consistency impact
Orphan-record count Referential integrity issue
Migration failure rate Deployment safety
Data-repair incidents Integrity maturity

2.15 Concurrency and Distributed-System Safety

Question: Is simultaneous processing safe?

Ask:

  • What happens when two requests modify the same entity?
  • Is optimistic or pessimistic locking required?
  • Can two workers process the same message?
  • Does the feature depend on exactly-once delivery?
  • Are distributed locks truly necessary?
  • What happens if the process crashes between a database write and event publication?
  • Are ordering requirements explicit?
  • Can stale events overwrite new data?
  • Can a retry be distinguished from a new request?

Useful metrics:

  • lock wait duration,
  • lock conflict rate,
  • deadlock count,
  • optimistic-concurrency conflict rate,
  • duplicate-message rate,
  • out-of-order event rate,
  • idempotency-key reuse rate,
  • transaction contention,
  • consumer lag,
  • and event retry count.

2.16 Testability

Question: Can the behavior be verified easily?

Testing should include:

  • domain unit tests,
  • application-service tests,
  • repository integration tests,
  • API tests,
  • contract tests,
  • end-to-end tests,
  • security tests,
  • load tests,
  • failure-injection tests,
  • migration tests,
  • and recovery tests.

Useful metrics:

Metric Description
Requirement coverage Acceptance criteria verified
Branch coverage Decision paths tested
Mutation score Tests detect intentional faults
Test flakiness Unreliable test percentage
Test execution time Feedback speed
Escaped-defect rate Defects reaching production
Contract coverage Public interfaces validated
Failure-path coverage Timeouts and conflicts tested
Test isolation Independent reproducibility
Test maintenance cost Suite brittleness

Measure coverage of risk and behavior, not only lines.

A payment feature with 95% line coverage but no concurrency or duplicate-request tests is still weak.


2.17 Observability

Question: Can we understand what the system is doing?

Implement:

Logging

  • structured logs,
  • stable event names,
  • appropriate severity,
  • correlation IDs,
  • trace IDs,
  • useful identifiers,
  • no secrets,
  • actionable error context,
  • and no duplicated logging at every layer.

Metrics

  • request count,
  • success count,
  • failure count,
  • business outcomes,
  • latency histograms,
  • queue depth,
  • dependency latency,
  • cache hit ratio,
  • retry count,
  • timeout count,
  • and domain-specific rejection reasons.

Tracing

  • one trace per request or job,
  • spans for databases and external services,
  • context propagation through messages,
  • useful attributes,
  • clear service names,
  • and exception details.

Useful indicators:

Metric Desired Direction
Mean time to detect Lower
Mean time to diagnose Lower
Unclassified errors Lower
Requests with trace context Higher
Actionable error context Higher
False-positive alerts Lower
Alert coverage Higher
Telemetry cost Controlled

A system that cannot explain its failures is difficult to operate.


2.18 Documentation

Question: Can others understand and maintain the solution?

Document:

  • feature purpose,
  • business invariants,
  • architecture,
  • data flow,
  • API contracts,
  • event contracts,
  • authentication,
  • authorization,
  • state transitions,
  • error behavior,
  • retries,
  • timeouts,
  • configuration,
  • database changes,
  • observability,
  • deployment,
  • rollback,
  • failure recovery,
  • known trade-offs,
  • and important architecture decisions.

Useful metrics:

  • public API documentation coverage,
  • architecture decision record coverage,
  • documentation freshness,
  • runbook coverage,
  • undocumented configuration count,
  • onboarding time,
  • and support questions caused by ambiguity.

3. βœ… At the End of Implementation

Before marking the feature complete, perform a final engineering review.


3.1 Functional Verification

Verify that:

  • all acceptance criteria are implemented,
  • business rules are correct,
  • invalid inputs are rejected,
  • boundary cases are handled,
  • duplicate requests are safe,
  • concurrent operations are safe,
  • expected errors are consistent,
  • and state transitions are valid.

3.2 Architecture Review

Verify that:

  • responsibilities are separated,
  • module boundaries are respected,
  • unnecessary coupling was not introduced,
  • circular dependencies do not exist,
  • public contracts are clear,
  • data ownership is clear,
  • the implementation matches the architecture,
  • and complexity remains justified.

3.3 API and Contract Review

Verify that:

  • request schemas are explicit,
  • response schemas are explicit,
  • error formats are consistent,
  • breaking changes are identified,
  • backward compatibility is preserved,
  • versioning is defined,
  • event schemas are documented,
  • and consumers tolerate additive changes.

3.4 Security Review

Verify that:

  • authentication tests pass,
  • authorization tests pass,
  • tenant isolation is verified,
  • input validation is verified,
  • rate limiting is verified,
  • secrets are protected,
  • logs contain no sensitive data,
  • dependencies are reviewed,
  • and abuse scenarios are tested.

3.5 Data Review

Verify that:

  • migrations are backward compatible,
  • rollback behavior is understood,
  • database constraints exist,
  • indexes match query patterns,
  • transactions are correct,
  • concurrent updates are safe,
  • duplicate data cannot be created,
  • and recovery and reconciliation are possible.

3.6 Deployment Readiness

Verify that:

  • configuration is validated,
  • health checks are available,
  • graceful shutdown works,
  • old and new versions can coexist,
  • feature flags are available where necessary,
  • rollback is possible,
  • dashboards are ready,
  • alerts are configured,
  • and operational documentation is complete.

4. πŸ§ͺ Testing Time

Testing should verify expected behavior, failure behavior, recovery behavior, and production limits.


4.1 Unit Tests

Test:

  • business rules,
  • validation logic,
  • state transitions,
  • calculations,
  • authorization policies,
  • retry decisions,
  • error mapping,
  • and domain behavior.

4.2 Integration Tests

Test:

  • database operations,
  • transactions,
  • cache behavior,
  • message brokers,
  • external services,
  • serialization,
  • authentication providers,
  • and repository implementations.

4.3 Contract Tests

Verify:

  • API request compatibility,
  • API response compatibility,
  • event-schema compatibility,
  • producer-consumer compatibility,
  • protocol compatibility,
  • backward compatibility,
  • and version compatibility.

4.4 End-to-End Tests

Test:

  • successful operation,
  • invalid operation,
  • unauthorized operation,
  • dependency failure,
  • timeout,
  • retry,
  • duplicate request,
  • concurrent request,
  • partial failure,
  • and recovery flow.

4.5 Performance Tests

Measure:

  • requests per second,
  • messages per second,
  • concurrent connections,
  • p50 latency,
  • p95 latency,
  • p99 latency,
  • CPU usage,
  • memory usage,
  • network usage,
  • database latency,
  • connection-pool usage,
  • queue lag,
  • cache hit rate,
  • and error rate under load.

Average latency is not enough.

Tail latency often reveals the real user experience.


4.6 Scalability Tests

Verify:

  • performance with multiple replicas,
  • throughput growth after adding replicas,
  • database behavior under increased load,
  • consumer scaling,
  • partition distribution,
  • autoscaling behavior,
  • load-balancer behavior,
  • connection limits,
  • and shared-resource bottlenecks.

The goal is not simply to add replicas.

The goal is to confirm that adding replicas creates useful capacity.


4.7 Resilience Tests

Simulate:

  • service unavailability,
  • database failure,
  • broker failure,
  • network delay,
  • network interruption,
  • slow dependency,
  • timeout,
  • process crash,
  • pod restart,
  • duplicate message,
  • out-of-order message,
  • and partial system failure.

Failure testing exposes assumptions that normal tests cannot reveal.


4.8 Security Tests

Test:

  • authentication bypass,
  • authorization bypass,
  • object-level authorization,
  • injection attacks,
  • invalid tokens,
  • expired tokens,
  • replay attacks,
  • excessive requests,
  • oversized payloads,
  • sensitive-data exposure,
  • and dependency vulnerabilities.

4.9 Migration and Recovery Tests

Verify:

  • database migration,
  • migration rollback,
  • mixed-version deployment,
  • backup restoration,
  • message replay,
  • dead-letter recovery,
  • data reconciliation,
  • and disaster recovery procedures.

A backup is useful only when restoration has been tested.


5. 🌍 Production-Time Metrics

Production metrics show whether the system behaves correctly under real conditions.


5.1 Traffic

Monitor:

  • requests per second,
  • messages per second,
  • concurrent users,
  • concurrent connections,
  • active consumers,
  • payload size,
  • traffic growth,
  • and peak traffic.

5.2 Latency

Monitor:

  • p50 latency,
  • p95 latency,
  • p99 latency,
  • database latency,
  • external-service latency,
  • queue waiting time,
  • message-processing time,
  • and connection-establishment time.

5.3 Errors

Monitor:

  • request error rate,
  • business failure rate,
  • timeout rate,
  • retry rate,
  • dependency failure rate,
  • message-processing failure rate,
  • dead-letter count,
  • serialization failure rate,
  • authentication failure rate,
  • and authorization failure rate.

Technical failures and business rejections should be measured separately.


5.4 Saturation

Monitor:

  • CPU usage,
  • memory usage,
  • event-loop lag,
  • thread-pool usage,
  • worker utilization,
  • database connection usage,
  • database lock waiting,
  • queue backlog,
  • consumer lag,
  • disk usage,
  • network bandwidth,
  • and file descriptor usage.

Saturation shows how close the system is to its operational limits.


5.5 Reliability

Monitor:

  • availability,
  • success rate,
  • SLO compliance,
  • error-budget consumption,
  • mean time to detect,
  • mean time to recover,
  • incident count,
  • retry success rate,
  • circuit-breaker state,
  • and recovery success rate.

5.6 Scalability

Monitor:

  • throughput per replica,
  • latency by replica count,
  • scaling efficiency,
  • autoscaling frequency,
  • autoscaling reaction time,
  • maximum sustainable throughput,
  • database bottlenecks,
  • hot partitions,
  • queue growth rate,
  • and connection growth per replica.

5.7 Data Quality

Monitor:

  • duplicate records,
  • failed transactions,
  • deadlocks,
  • constraint violations,
  • reconciliation mismatches,
  • orphaned records,
  • replication lag,
  • stale reads,
  • out-of-order events,
  • and duplicate messages.

Data failures may exist even when every API returns success.


5.8 Security

Monitor:

  • suspicious request count,
  • rate-limit activations,
  • unauthorized-access attempts,
  • invalid-token count,
  • account-lock events,
  • security incidents,
  • vulnerable dependencies,
  • secret exposure,
  • abnormal traffic patterns,
  • and audit-log completeness.

5.9 Business Metrics

Monitor:

  • successful business operations,
  • failed business operations,
  • feature usage,
  • completion rate,
  • processing time,
  • user-visible failures,
  • abandoned operations,
  • manual intervention count,
  • support-ticket count,
  • and business-result accuracy.

A technically healthy service can still fail its business purpose.


5.10 Cost

Monitor:

  • cost per request,
  • cost per message,
  • cost per active user,
  • database cost,
  • broker cost,
  • storage cost,
  • network-egress cost,
  • logging cost,
  • tracing cost,
  • third-party API cost,
  • and cost per service replica.

A scalable solution can still be financially inefficient.


6. πŸ“¦ Dependency and Supply-Chain Quality

Every dependency adds:

  • security risk,
  • maintenance effort,
  • licensing concerns,
  • compatibility risk,
  • transitive dependencies,
  • and build complexity.

Ask:

  • Is the dependency necessary?
  • Is it actively maintained?
  • Is its license compatible?
  • How many transitive dependencies does it add?
  • Does it execute install scripts?
  • Does it duplicate existing capability?
  • Is its API stable?
  • Can it be isolated behind an adapter?
  • What happens if maintenance stops?
  • Would a small internal implementation be safer?

Useful metrics:

  • direct dependency count,
  • transitive dependency count,
  • known vulnerability count,
  • dependency freshness,
  • unmaintained dependency count,
  • package size,
  • license violations,
  • update frequency,
  • and time to patch vulnerabilities.

7. πŸ‘₯ Team Ownership and Governance

A feature should have clear ownership.

Ask:

  • Which team owns the feature?
  • Who responds to incidents?
  • Who owns the data?
  • Who approves contract changes?
  • Is the feature inside the correct bounded context?
  • Is there a clear review path for security and database changes?
  • Is responsibility spread so widely that nobody owns it?

Useful metrics:

  • unowned components,
  • review turnaround time,
  • bus factor,
  • cross-team dependency count,
  • ownership ambiguity incidents,
  • time to find the responsible team,
  • and number of repositories changed for one feature.

8. 🎯 User and Business Effectiveness

Technical quality must connect to business outcomes.

Measure:

  • feature adoption rate,
  • task completion rate,
  • business success rate,
  • user-visible error rate,
  • conversion improvement,
  • support-ticket rate,
  • processing time saved,
  • manual intervention reduction,
  • abandonment rate,
  • incorrect-result rate,
  • and customer-impacting incident count.

A feature that is perfectly architected but unused or ineffective is not successful.


9. 🧭 Simple Decision Template

Use this template to compare candidate solutions.

Property Question
Purpose What problem does it solve?
Suitability Does it match the workload and communication model?
Complexity How much implementation and operational complexity does it add?
Performance What latency and throughput can it provide?
Scalability Can it scale horizontally and handle future growth?
Reliability How does it behave during failures?
Consistency What consistency guarantees does it provide?
Security How are identity, access, data, and abuse handled?
Compatibility Does it work with current clients and infrastructure?
Maintainability Can the team understand and support it?
Observability Can failures and performance problems be diagnosed?
Cost What are its implementation and production costs?
Risk What failure modes and dependencies does it introduce?

10. πŸ“‹ Candidate Comparison Example

Suppose a team must choose between REST, gRPC, and asynchronous messaging.

Criterion REST gRPC Message Broker
Communication model Request-response Request-response and streaming Asynchronous messaging
Browser support Excellent Limited without a gateway Indirect
Payload efficiency Moderate High Depends on serialization
Coupling Temporal coupling Temporal coupling Reduced temporal coupling
Delivery guarantee Request-based Request-based Broker-dependent
Streaming Limited Strong Event-driven
Operational complexity Low Medium Medium to high
Best use case Public and internal APIs High-performance internal RPC Async workflows and events

There is no universal winner.

The correct choice depends on:

  • requirements,
  • scale,
  • failure behavior,
  • consistency needs,
  • team expertise,
  • and operational constraints.

11. πŸ“Š Recommended Scoring Model

Score each important dimension from 0 to 5.

Score Meaning
0 Not considered
1 Serious unresolved risk
2 Partially addressed
3 Acceptable for current requirements
4 Strong implementation
5 Explicitly designed, measured, and verified

Do not average all scores blindly.

A feature with an average score of 4.2 is still unacceptable if authorization scores 1.


Release-Blocking Dimensions

A serious failure in any of these should block release:

  • functional correctness,
  • authorization,
  • security,
  • data integrity,
  • migration safety,
  • concurrency safety,
  • reliability for critical flows,
  • and compliance requirements.

12. 🚦Practical Feature Gate

Before Implementation

[ ] Business behavior and invariants are explicit
[ ] Expected workload and latency targets are defined
[ ] Security and authorization boundaries are defined
[ ] Data ownership and transaction boundaries are defined
[ ] Failure, timeout, retry, and idempotency behavior are defined
[ ] API and event compatibility requirements are known
[ ] Simpler alternatives were considered
Enter fullscreen mode Exit fullscreen mode

During Implementation

[ ] Transport logic is separated from business logic
[ ] Application services orchestrate use cases
[ ] Domain rules are independent of infrastructure
[ ] External providers are behind explicit adapters
[ ] Validation and output mapping are explicit
[ ] Database constraints protect important invariants
[ ] External calls have timeout and failure handling
[ ] Logs, metrics, and traces are implemented
[ ] Success and failure paths are tested
[ ] No unnecessary dependency or abstraction was added
Enter fullscreen mode Exit fullscreen mode

Before Merge

[ ] Acceptance criteria pass
[ ] Authorization tests pass
[ ] Duplicate and concurrent request behavior is tested
[ ] Database query plans and query counts are reviewed
[ ] p95 and p99 latency are measured where relevant
[ ] Static analysis and dependency scanning pass
[ ] Public contracts are documented
[ ] Migrations are backward compatible
[ ] Rollback or feature disablement is possible
[ ] Dashboards and alerts are available
Enter fullscreen mode Exit fullscreen mode

After Deployment

[ ] Business success rates are monitored
[ ] Latency, traffic, errors, and saturation are monitored
[ ] Database and external dependency behavior is monitored
[ ] Cost and resource utilization are reviewed
[ ] Error-budget and SLO impact are reviewed
[ ] User and business outcomes are measured
[ ] Technical debt and follow-up work are recorded
Enter fullscreen mode Exit fullscreen mode

13. 🚦Final Decision Rule

Do not select a protocol, pattern, database, framework, or microservice architecture only because it is popular.

Select it only when:

  • it solves the actual requirement,
  • its consistency guarantees are appropriate,
  • its delivery guarantees are appropriate,
  • its performance matches the workload,
  • its operational complexity is acceptable,
  • the team can maintain it,
  • it can be tested,
  • it can be observed,
  • it behaves safely during failure,
  • its security risks are controlled,
  • its cost is justified,
  • and it remains suitable as the system grows.

βœ… When Is a Feature Actually Done?

A feature is not done only because:

  • the code is complete,
  • unit tests pass,
  • QA approved it,
  • or it was deployed successfully.

A backend feature is ready when:

βœ… Business requirements are satisfied
βœ… Architecture decisions are justified
βœ… Responsibilities are clear
βœ… Contracts are stable
βœ… Security is verified
βœ… Data integrity is protected
βœ… Failure behavior is tested
βœ… Performance is measured
βœ… Scalability is understood
βœ… Observability is available
βœ… Deployment and rollback are safe
βœ… Production metrics are defined
βœ… The team can maintain the solution
Enter fullscreen mode Exit fullscreen mode

πŸ’¬ Final Thought

The best engineering teams do not ask only:

Can we build it?

They ask:

Can we build it correctly, securely, reliably, efficiently, and sustainably?

That is the purpose of the Backend Engineering Evaluation Framework.

It is not a framework for choosing the most advanced technology.

It is a framework for choosing the most appropriate solution.

This version is ready to paste into Dev.to as a complete Markdown article.

Top comments (0)