codejump

AcademyDesign Patterns

Facade pattern

Hiding a multi-step subsystem behind one simple call, the second thing to maintain the facade can become, and the wall it becomes once it is the only way in.

5 min readUpdated

3 exercises

Waiting at the end of this page.

Facade hides complexity rather than translating or adding to it: one simple entry point standing in front of a subsystem that has several moving parts and a specific order they need to run in.

A Facade doesn't add behavior or translate an interface, it hides one. Several subsystems each with their own setup order and quirks get collapsed behind a single method that knows the right sequence, so callers stop needing to know it too.

The problem it solves

Starting your application takes three steps: connect to the database, warm the cache, initialize authentication. The order matters, because the cache warm-up reads from the database and authentication needs both.

If every entry point repeats those steps, you get problems that only show up later:

  • Duplicated sequences. The API server, the background worker and the test setup each copy the three calls.
  • Order bugs. One copy swaps two lines and the failure only appears in that entry point.
  • Coupling. Every caller knows the internals of three subsystems, so changing one touches all of them.

The fix is one object that owns the sequence and exposes a single method. Callers say what they want, start(), and the facade knows how.

Structure

The client makes one call. The facade runs the subsystems in the right order, and the client never sees them
The client makes one call. The facade runs the subsystems in the right order, and the client never sees them

Two parts:

  • The subsystems: the classes doing the real work (Database, Cache, Auth). They stay unchanged and know nothing about the facade.
  • The facade (AppFacade): a class exposing a small, task-oriented interface and orchestrating the subsystems.
class Database { connect() { return 'db-connected'; } }
class Cache { warm() { return 'cache-warmed'; } }
class Auth { init() { return 'auth-ready'; } }

class AppFacade {
  constructor() {
    this.db = new Database();
    this.cache = new Cache();
    this.auth = new Auth();
  }
  start() {
    return [this.db.connect(), this.cache.warm(), this.auth.init()];
  }
}

// new AppFacade().start() → ['db-connected', 'cache-warmed', 'auth-ready']

The facade is not a wall. Advanced callers can still reach the subsystems directly when they need something the facade doesn't offer. It exists to make the common path short, not to forbid the rest.

Where it is used in real systems

A route calls one service method. The service coordinates inventory, payments, email and analytics
A route calls one service method. The service coordinates inventory, payments, email and analytics
Use caseWhat the facade hides
Service layerplaceOrder() coordinating inventory, payments, email and analytics.
Application bootstrapDatabase, cache, queues and auth started in the right order.
SDK wrappersA Storage.upload() hiding signed URLs, multipart uploads and retries.
Complex librariesA simple render(template, data) over a parsing and compiling pipeline.
Legacy systemsA clean API in front of a tangle of old modules.
Media conversionconvert(file, 'mp4') hiding codecs, buffers and temp files.
Test setupOne createTestApp() that builds the server, database and fixtures.

If a piece of code calls three or four other objects in a fixed order just to do one thing, that sequence wants to be a facade.

Facades you already use

  • `fetch(url)` hides sockets, redirects, headers and streaming behind one call.
  • jQuery `$` was a facade over the inconsistent browser DOM APIs.
  • Prisma Client is a facade over connection pooling, query building, SQL generation and result mapping.
  • NestJS and Angular services. A service that composes several repositories or clients behind business-level methods.
  • `git pull` runs fetch then merge. A small facade over two commands.

Facade, Adapter and Mediator

What it doesDirection
FacadeOffers a simpler interface to a subsystemCallers to the subsystem
AdapterMakes one interface match anotherBetween two incompatible interfaces
MediatorCoordinates objects that talk to each otherBetween peers

A facade only simplifies. The subsystems don't know it exists. A mediator, by contrast, is known to the objects it coordinates, and they talk through it.

When not to use it

  • The subsystem is already simple. A facade over one class that has one method is a pointless layer.
  • It becomes a god object. A facade that grows every method any caller ever wanted turns into a dumping ground. Keep several small facades, each for one task.
  • It contains business rules. A facade coordinates, it doesn't decide. When it starts holding logic, that logic belongs in a real service.
  • It blocks needed access. If callers must reach around it constantly, the facade is missing something.

What interviewers ask

  • "What is the Facade pattern?" A simple interface to a complex subsystem.
  • "Facade versus Adapter?" A facade simplifies many things. An adapter reshapes one interface to match another.
  • "Does the facade replace the subsystem?" No. The subsystems remain available. The facade is a convenience.
  • "Give a real example." A service layer method that coordinates several repositories, or Prisma Client.
  • "How does it help testing?" Callers depend on one small interface, so it is easy to fake, instead of mocking three subsystems.

The mistake to avoid

A Facade that does the work itself instead of delegating. Once AppFacade contains connection logic or cache rules of its own, it has become a fourth subsystem and callers cannot tell what is simple entry point and what is logic. The facade should only call the subsystems, in order, and return.

The mechanism above, one object calling several others in a fixed order, is the same in JavaScript, Python or Java. Only the syntax changes.

Now practice it

1 challenge · 2 quizzes

Reading this page is the cheap half. These are the exercises that make you use it.