Skip to main content

0002. Use Node.js, Express, and SQLite for Backend Examples

Date: 2025-11-18

Status

Accepted

Context

The devfoundry curriculum requires a backend stack for teaching fullstack development (Stage 4 of the lemonade stand progression).

Requirements:

  • Must be accessible to JavaScript-proficient learners (minimize language switching)
  • Must demonstrate core backend concepts (HTTP, APIs, persistence) clearly
  • Must be simple to set up locally (no complex infrastructure requirements)
  • Must have strong AI assistant support
  • Must be practical for small-to-medium projects (realistic for final projects)
  • Must teach transferable backend patterns

Target audience considerations:

  • Learners are already using JavaScript for frontend (React)
  • Total beginners benefit from language consistency
  • Goal is understanding backend concepts, not mastering a specific backend language

Runtime alternatives:

OptionProsCons
Node.jsJavaScript (same as frontend), vast ecosystem, AI-friendlySingle-threaded model can be confusing, callback hell risks
Python (Flask/FastAPI)Beginner-friendly syntax, excellent for APIsIntroduces new language, less AI training data for web
GoFast, great concurrency, growing popularityCompiled language, steeper learning curve, verbose for small examples
Ruby (Rails)Convention over configuration, rapid developmentDeclining adoption, less relevant for job market

Framework alternatives (assuming Node.js):

OptionProsCons
ExpressMinimalist, unopinionated, industry standardMore boilerplate, manual configuration
FastifyFaster, modern, better TypeScript supportSmaller community, less AI training data
NestJSEnterprise-grade, Angular-likeOver-engineered for simple examples, steep learning curve
HonoModern, edge-ready, lightweightVery new, limited ecosystem

Database alternatives:

OptionProsCons
SQLiteZero config, portable, file-basedNot production-scalable, no concurrency handling
PostgreSQLProduction-grade, feature-rich, freeRequires separate server, complex setup for beginners
MySQLPopular, well-documentedRequires separate server, similar complexity to PostgreSQL
MongoDBNoSQL, flexible schemaDoesn't teach SQL, less structured

Decision

Use Node.js runtime with Express framework and SQLite database for all fullstack examples.

Specific implementation:

  • Node.js 18+ (LTS version for stability)
  • Express 4.x (stable, well-documented)
  • SQLite via better-sqlite3 package (synchronous API, simpler for beginners)
  • RESTful API design (standard HTTP methods)
  • JSON for request/response format
  • TypeScript for type safety (gradual adoption from Stage 4+)

Project structure convention:

server/
db/
lemonade.db # SQLite database file
schema.sql # Database schema definition
routes/
orders.js # Order-related endpoints
middleware/
errorHandler.js # Error handling
server.js # Main server file

Database choice rationale:

  • SQLite for Stages 4-5 (learning)
  • Document migration path to PostgreSQL for production (in ADR or guide)
  • Teach SQL concepts that transfer to any relational database

API design pattern:

GET    /api/orders           # List all orders
POST /api/orders # Create new order
GET /api/orders/:id # Get specific order
PUT /api/orders/:id # Update order
DELETE /api/orders/:id # Delete order

Consequences

Positive:

  • Language consistency: Same JavaScript knowledge applies frontend and backend
  • Reduced cognitive load: No context switching between languages
  • AI assistant support: Excellent — Node + Express is extremely well-represented in training data
  • Ecosystem: npm provides access to millions of packages
  • Industry relevance: Node.js + Express is widely used in startups and mid-size companies
  • Setup simplicity: SQLite requires zero configuration, no separate database server
  • Portability: Entire project (code + data) is file-based, easy to share and deploy
  • SQL learning: Demonstrates relational database concepts with standard SQL
  • Async patterns: Teaches promises and async/await in backend context

Negative:

  • Single-threaded: Node's event loop can be confusing for beginners
  • SQLite limitations: Not suitable for high-concurrency production apps
  • Express verbosity: More boilerplate than some modern frameworks (Fastify, Hono)
  • Callback pitfalls: Easy to write nested callback code (mitigated by async/await)
  • Limited to I/O: Not ideal for CPU-intensive tasks (not relevant for this curriculum)

Neutral:

  • Not "best" for production: Python/Go might be better for some use cases
  • Ecosystem churn: JavaScript tooling changes rapidly (but core concepts stable)

Mitigation strategies:

  • Clear documentation: Explain event loop and async patterns with diagrams
  • Async/await from start: Use modern async patterns, avoid callback hell
  • SQLite caveats: Explicitly teach when to graduate to PostgreSQL/MySQL
    • Add a guide: "From SQLite to PostgreSQL" (ADR-0007 or separate doc)
  • RESTful patterns: Teach standard REST so concepts transfer to any backend
  • Error handling: Introduce middleware pattern early to handle errors gracefully
  • Type safety: Use TypeScript to catch common backend errors (undefined properties, wrong types)

Production deployment considerations:

  • For Stage 5 (deployment), document:
    • When SQLite is acceptable (low-traffic apps, prototypes)
    • How to migrate to PostgreSQL (connection string, minimal code changes)
    • Deployment platforms: Render, Railway, Fly.io (support Node + Postgres)

Advanced curriculum extensions (future):

  • Module on database migrations (PostgreSQL)
  • Module on authentication (JWT, sessions, OAuth)
  • Module on scaling (load balancing, caching, workers)
  • ADR-0001: Frontend Stack — Node aligns with JavaScript ecosystem
  • ADR-0004: Database Choice for Learning — (future) Deep dive on SQLite vs others
  • ADR-0005: Deployment Platform — (future) Where to host Node + SQLite