DEV Community

Insight 105
Insight 105

Posted on

Data Integrity & Anti-Cheating

Online exam systems almost always face two main enemies:

  1. Creative cheating behavior from test-takers
  2. Unreliable network conditions

Therefore, the exam system backend must be designed with a paranoid by design mindset:

  • Never trust data from the client
  • Assume the connection can drop at any time
  • Ensure the system remains consistent even if partial failures occur

In this chapter, we will discuss the Academic Suite strategy in maintaining exam data integrity whilst minimizing opportunities for cheating.


6.1 Async Logging for Performance and Scalability

Most anti-cheating mechanisms are observational, such as detecting tab switching or loss of browser focus.

Every time a student switches tabs (e.g. using Alt + Tab), the frontend sends a FOCUS_LOST event to the backend.

The problem is, these events can occur massively and simultaneously.

Imagine:

  • 1,000 students
  • 1 exam
  • Alt-tabbing at nearly the same time

If the backend processes this logging synchronously, the database can become a bottleneck and slow down main requests.

Solution: Asynchronous Logging with Goroutines

Academic Suite uses goroutines to record events in a fire-and-forget manner.

Implementation in handlers/log.go:

func LogEvent(eventType string, ...) {
    go func() {
        database.DB.Create(&log)
    }()
}
Enter fullscreen mode Exit fullscreen mode

With this approach:

  • HTTP requests can be completed immediately
  • Logging does not hinder main system performance
  • The system remains responsive even if there is a surge in events

This approach is highly effective for non-critical data that serves as an audit trail.


6.2 Answer Integrity (Autosave & Idempotency)

A question that almost always arises from students is:

"If the internet goes down, will my answers be lost?"

Academic Suite addresses this concern with two main mechanisms.

Autosave per Question

Every time a student selects or changes an answer:

  • The frontend sends a request to the backend immediately
  • The /api/attempts/:id/answers endpoint saves the change

In this way, every answer is saved almost in real-time.

Idempotency

Slow or unstable connections can cause:

  • Requests to be sent repeatedly
  • Buttons to be clicked multiple times

The backend must ensure that this condition does not cause data duplication.

Idempotency implementation is done with an upsert pattern:

// handlers/attempt.go
if err := database.DB
    .Where("attempt_id = ? AND question_id = ?", ...)
    .First(&existing); err == nil {

    existing.SelectedOptionID = newValue
    database.DB.Save(&existing)
}
Enter fullscreen mode Exit fullscreen mode

With this approach:

  • Only the latest answer is saved
  • Data remains consistent even if requests are sent repeatedly

6.3 Force Submit as Fail-Safe Mechanism

The worst-case scenario in an online exam is:

  • Exam time runs out
  • Student's browser crashes or closes
  • Submit request is never sent

Without additional mechanisms, the student's attempt can remain stuck in Active status forever.

Solution: Force Submit

Academic Suite provides a special endpoint for teachers:

POST /api/attempts/:id/force-submit
Enter fullscreen mode Exit fullscreen mode

This endpoint will:

  1. Retrieve all saved answers
  2. Calculate the score based on that data
  3. Change the attempt status to Submitted

Thus:

  • No attempt is stuck in an invalid status
  • Teachers have full control over exam completion
  • The system remains consistent even if client-side failure occurs

6.4 Client Action Restrictions (Disable Right Click & Copy)

As an additional anti-cheating layer, Academic Suite also restricts several client-side actions during the exam, such as:

  • Right Click
  • Copy text (Ctrl+C / Cmd+C)
  • Select text in the question area

The goal is not for absolute security, but to:

  • Reduce casual cheating
  • Increase friction for participants intending to copy questions
  • Support behavior-based monitoring

Frontend Implementation

This restriction is applied only when exam status is active, and is automatically removed after the exam finishes.

Example implementation in React:

useEffect(() => {
  const prevent = (e: Event) => e.preventDefault()

  document.addEventListener('contextmenu', prevent)
  document.addEventListener('copy', prevent)

  return () => {
    document.removeEventListener('contextmenu', prevent)
    document.removeEventListener('copy', prevent)
  }
}, [])
Enter fullscreen mode Exit fullscreen mode

Important Note

  • These restrictions are easy to bypass by experienced users
  • Therefore, this feature does not stand alone
  • Its main value is as an additional layer (defense in depth) combined with:

    • Behavior logging
    • Server-side authority
    • Post-exam analysis

This approach aligns with modern exam system principles: make cheating difficult, don't claim it's impossible.


Chapter Summary

In this chapter, we close the entire discussion of the Academic Suite backend with a focus on system resilience.

We discussed:

  • Asynchronous logging for performance
  • Autosave and idempotency for answer integrity
  • Fail-safe mechanisms through force submit

With this approach, the exam system becomes:

  • Secure
  • Resilient to network disruptions
  • Difficult to manipulate

In the next section, we will switch to frontend implementation and start building the user interface.

Part 3 begins with Chapter 7: React Application Architecture.

Top comments (0)