Phase 3 · Databases & Persistent DataModule 24~100 min read

Phase Project: Data-Backed Task API

Replace JSON storage with PostgreSQL, migrations, transactions, integration tests, and a measured Redis read cache.

What you'll learn

Replace file persistence with a production-shaped data layer. Combine PostgreSQL migrations, repositories, transactions, Redis, integration tests, and operational lifecycle into one coherent task API.

By the end of this lesson, you'll be able to:

  • Deliver a migrated schema
  • Preserve service contracts
  • Protect multi-step writes
  • Add and verify a safe cache

Core mental model

Node.js becomes easier when you separate the JavaScript language from the runtime and the operating-system capabilities it exposes. Use this table as a decision guide.

ConceptWhat it meansDecision rule
Source of truthThe system owning durable stateKeep PostgreSQL authoritative and Redis disposable
AdapterInfrastructure implementing an application portInject it at the composition root
Acceptance evidenceProof that requirements holdCover correctness, concurrency, recovery, and operability

Professional workflow

Build and verify Node.js programs from the terminal in small, observable steps.

  1. Define the durable API boundary: inputs, outputs, invariants, ownership, and expected failures.
  2. Design the data or message contract before choosing implementation details.
  3. Implement the smallest correct path with dependencies passed explicitly.
  4. Add validation, failure translation, cleanup, and concurrency behavior.
  5. Verify the boundary with realistic data and at least one adversarial case.
  6. Measure or observe the behavior before optimizing or extracting abstractions.

Keep the feedback loop short

Run the smallest useful command after every meaningful change. Read the complete error message before editing again, and keep inputs and outputs visible while you learn.

Guided code lab

Compose infrastructure at startup

Routes receive services; services receive ports; adapters own infrastructure.

main.js
const tasks = createPostgresTaskRepository({ pool });
const cached = createCachedTaskRepository({ tasks, redis, ttlSeconds: 60 });
const service = createTaskService({ tasks: cached, clock, ids });
const app = createApp({ taskService: service });

const server = app.listen(config.port);
installShutdown({ server, close: () => Promise.all([pool.end(), redis.quit()]) });

Test the complete contract

This crosses HTTP, service, repository, and a real database.

tasks.test.js
test('creates and lists an owner task', async () => {
  const created = await api.post('/tasks', token, { title: 'Ship phase 3' });
  assert.equal(created.status, 201);
  const listed = await api.get('/tasks?status=open', token);
  assert.equal(listed.body.items[0].id, created.body.id);
});

Production practice

Contract

The public HTTP contract stays stable while JSON storage is replaced by database and cache adapters.

Verification

Run migrations from empty, all API tests, concurrent writes, Redis outage tests, query plans, and shutdown checks.

Operations

Document configuration, migration order, pool budgets, backups, health semantics, cache metrics, and recovery commands.

Common failure mode

A working happy path is not production readiness. Migration failure, cache outage, concurrency, and shutdown are product behavior.

Independent workshop

Complete and present the Phase 3 data-backed task API.

Your finished workshop must include:

  • Migration-managed schema
  • Parameterized repository
  • Transactional operation
  • Redis fallback
  • End-to-end tests
  • Operations README

Definition of done

Run the happy path and at least two edge cases, keep responsibilities separated, and add a short README explaining how to run the program.

Recap & quick check

Key takeaways

  • Boundaries make adapters replaceable
  • PostgreSQL owns truth
  • Transactions protect invariants
  • Redis accelerates
  • Evidence completes features

Quick check

1. Where should adapters be assembled?

2. What if Redis is unavailable?

3. What proves migration health?

Next: Web Security & Threat Modeling