Reference

Data Flow Patterns in Public Agencies

Every government service moves information from one place to another. Most of the cost, delay, and failure lives in how it moves. This page draws the common patterns, plainly, one at a time.

Pattern 1: Static website vs. database-backed website

Start with the most common question a public web team faces, even if nobody says it out loud: when a resident visits a page on your website, where does that page come from?

There are two common answers, and the difference between them once decided which parts of a famous federal website stayed standing.

The database-backed way

Most content management systems — WordPress and Drupal are the big names — work like a short-order kitchen. The page does not exist until someone orders it.

When a visitor asks for a page, a web server receives the request, asks a database for the content, waits for the answer, assembles the content into a page, and sends the finished page back.

sequenceDiagram
    participant V as Visitor's browser
    participant W as Web server
    participant D as Database
    V->>W: Ask for a page
    W->>D: Look up this page's content
    D-->>W: The content, as raw data
    Note over W: Assemble the content<br/>into a finished page
    W-->>V: The finished page

This happens for every visit. A thousand visitors means a thousand round trips to the database, each one assembled to order.

There are good reasons this pattern became the default. Editors get a friendly editing screen. Content lives in one organized place. The same database can also power search, logins, and forms.

But look at the diagram again. The visitor is waiting on every arrow. If the database is slow, every page is slow. If the database is down, every page is down — including pages whose content has not changed in three years. The database is a single point that everything else stands on.

The static way

A static website works like a printed handout instead of a short-order kitchen. The pages are built ahead of time — once, when the content changes — and stored as complete, finished files in a simple storage service, such as a cloud bucket.

When a visitor asks for a page, the storage service hands over the file. That is the whole transaction.

sequenceDiagram
    participant V as Visitor's browser
    participant S as File storage (cloud bucket)
    V->>S: Ask for a page
    S-->>V: The page, already finished
    Note over S: Nothing is computed.<br/>The page existed before<br/>anyone asked for it.

No query, no waiting on a database, no assembly. The work of building the page happened earlier, exactly once, out of the visitor’s way.

Serving a file is about the cheapest, most reliable thing a computer can do. Storage services do it for pennies, at almost any scale, and there is very little to break and very little for an attacker to attack — there is no live software on the page’s path to compromise.

What HealthCare.gov taught everyone

On October 1, 2013, HealthCare.gov launched, and its collapse became national news.

The detail that matters here is which part collapsed.

The informational side of the site — the pages explaining the law, the plans, the deadlines — had been built as a static site: finished pages, built ahead of time, served as files. Those pages held up.

The application side — creating an account, checking eligibility, enrolling — was dynamic. Every click depended on a chain of live systems and databases answering in real time, and when several times the expected crowd arrived at once, that chain jammed. Visitors were left staring at error screens, not because the content failed, but because the machinery assembling responses on the fly could not keep up.

Federal web teams took the lesson. In the years since, much of the government web has moved to the static pattern for anything that is fundamentally content — hundreds of federal and agency sites now publish this way, and platforms like cloud.gov Pages exist specifically to do it. The rule of thumb that emerged: never make a resident’s request wait on a database unless the page genuinely depends on who is asking.

Side by side

  Database-backed Static
When the page is built At the moment of each visit Ahead of time, when content changes
What a visit touches Web server + database, live A stored file
When the database has a bad day The whole site does too Nothing happens; visitors never touch it
Hosting cost A server (or several) running around the clock Pennies for file storage
Security surface Live software to patch and defend on every page Almost nothing on the page’s path
Editing Friendly editing screens, instant publish Requires a publishing step after edits

Where a database still belongs

Static is not a verdict against databases. It is a verdict about where they belong: behind the pages that genuinely need them, and off the path of the pages that don’t.

Some things only a live system can do. Searching thousands of records that change daily. Logging in and seeing your own case, your own bill, your own application status. Accepting a form submission. Anything where two visitors should rightly see two different pages.

The pattern that works is separation. Publish everything that is the same for every visitor — which for most agencies is the large majority of the website — as static files. Keep the live, database-backed pieces small, separate, and behind their own doors, so that when one of them has a bad day, the phone number, the office hours, and the “how do I apply” page are still standing.

And honestly: a well-run database-backed site can be tuned toward this too, by putting caches in front of it so most visitors receive a saved copy instead of a fresh assembly. That works — but notice what it is. It is an imitation of the static pattern, bolted onto the dynamic one, with more moving parts than either.

The question to ask your web team or vendor: does every visitor see the same page here? If yes, that page should be built ahead of time and served as a file. If no, that page has earned its database — keep it small and keep it separate.


Pattern 2: Forms and intake

The first pattern was about information flowing out — pages going to visitors. This one is about information flowing in. A resident needs to tell the agency something: an application, a renewal, a complaint, a request.

The most common flow, still, is the fillable PDF.

The PDF way

The website offers a form to download. The resident prints it, fills it in by hand, and sends it back — by mail, by email, or across a counter. Then a staff member reads the handwriting and types the answers into the actual system.

sequenceDiagram
    participant R as Resident
    participant Q as Mailroom / shared inbox
    participant S as Staff member
    participant Sys as Agency system
    R->>Q: Filled-out PDF, sent in
    Note over Q: Sits in a queue<br/>with everything else
    S->>Q: Pick up the submission
    S->>Sys: Re-type the answers by hand
    Sys-->>S: Rejected — a required field is blank
    S->>R: Letter or call: please resubmit
    Note over R: Back to the start,<br/>weeks after submitting

Look at where the work lands. The resident wrote the information down once, on paper. Staff write it down again, into the system. The same information is entered twice, with handwriting in between — and every re-entry is a chance for the copies to disagree.

Now look at where errors surface. The blank field is discovered at re-typing time, days or weeks after submission — when fixing it means reaching back to the resident and starting the queue over. The resident could have fixed it in ten seconds on the day they applied. Nobody asked them then.

The structured way

A web form checks the answers at the door.

sequenceDiagram
    participant R as Resident
    participant F as Web form
    participant Sys as Agency system
    R->>F: Fill out the form
    F-->>R: A required field is blank — flagged immediately
    R->>F: Fix it and submit
    F->>Sys: A complete, structured record — entered once
    Sys-->>R: Confirmation, with a reference number

The blank field costs ten seconds instead of three weeks. The information is entered once, by the person who knows it best, and arrives as a structured record staff can work with instead of handwriting staff must decode. And the resident leaves holding a reference number, which is the difference between “I sent it in” and “it exists, and I can point to it.”

A form is one of the things that genuinely needs a live piece — this is exactly the separation rule from Pattern 1. A mostly-static website with one small form service behind it is a common and healthy shape: the live part stays tiny, and the rest of the site cannot be taken down by it.

Paper should remain an option — not everyone is online. The pattern is not about closing the paper door. It is about what happens to the information once it arrives: whether it flows onward as structured data, or waits for a person to re-type it.

The question to ask: when a resident submits this form, does a person re-type it into something else? Every re-typing is a delay, an error rate, and a cost — hiding in plain sight.


Pattern 3: The nightly batch file

Inside an agency, systems need to share information with each other. The permit system needs to tell the finance system what was paid. The finance system needs to tell the reporting system what came in.

The most common way they do it is the nightly batch file. Once a day, usually in the small hours, one system exports its new records into a file. The file is dropped on a shared server. Later that morning, the other system picks the file up and imports it.

sequenceDiagram
    participant A as Permit system
    participant F as File server
    participant B as Finance system
    Note over A: 2:00 a.m.
    A->>F: Export yesterday's records as a file
    Note over F: 5:00 a.m.
    B->>F: Pick up the file
    B->>B: Import the records
    Note over B: Staff arrive to<br/>yesterday's data — every day

This pattern is everywhere, it is decades old, and it mostly works. It is the static-website idea applied between systems: prepare the data ahead of time, hand over a finished file, keep the systems out of each other’s way. Nothing about “batch” deserves scorn.

Two things about it are worth seeing clearly, though.

The data is always yesterday’s. One nightly file means a one-day lag. A chain of systems, each passing files nightly, means the lags add up. When a resident hears “please allow two to three business days for your payment to show,” that is usually not a person working for three days. It is a chain of nightly files, each waiting for its scheduled hour. The delay is cadence, not effort — and knowing that changes what “faster” would take.

It fails silently. A jammed export looks exactly like a quiet night.

sequenceDiagram
    participant A as Permit system
    participant F as File server
    participant B as Finance system
    Note over A: 2:00 a.m. — export fails quietly
    B->>F: Pick up the file
    F-->>B: Only the old file is there
    B->>B: Imports it again, reports success
    Note over B: Nobody is alerted.<br/>Discovered weeks later,<br/>during reconciliation.

The fix is not expensive. The receiving side checks that a file arrived, that it is dated today, and that the record count looks sane — and raises a loud alarm when any of that fails. A transfer that cannot announce its own failure will eventually fail without announcement.

The question to ask: for each nightly file, what happens on the morning it doesn’t arrive — and who finds out?


Pattern 4: Open data feeds

The first pattern was pages flowing out to people. This one is data flowing out to programs — other agencies’ systems, researchers, journalists, civic apps, and increasingly, software assistants acting on a resident’s behalf.

The by-request way

The default, in most agencies, is that data leaves by request. Someone emails, or files a public records request. A staff member queries the system, exports a spreadsheet, and emails it back.

sequenceDiagram
    participant P as Person or program that needs the data
    participant S as Staff member
    participant Sys as Agency system
    P->>S: Request the data (email, records request)
    Note over S: Days or weeks in a queue
    S->>Sys: Query and export
    S-->>P: A spreadsheet, by email
    Note over P: A one-time copy, aging already.<br/>Next month: ask again.

Every request costs staff time. Every requester gets a slightly different copy. And the copy starts going stale the moment it is sent, so the same question comes back next month.

The published way

The alternative is to publish the data as files — comma-separated, JSON, XML — on a schedule, at a stable web address, in the same simple file storage that serves the website.

sequenceDiagram
    participant Sys as Agency system
    participant B as File storage (same bucket as the website)
    participant C as Anyone's program
    Note over Sys: Nightly, on a schedule
    Sys->>B: Publish the data as files (.csv / .json)
    C->>B: Fetch the file at its stable address
    B-->>C: The data, current as of last night
    Note over C: No queue, no staff time,<br/>the same answer for everyone

Here is the idea underneath, and it connects everything on this page. A webpage is the agency answering a question for a person — “when does the council meet,” “what does a permit cost.” A data file at a stable address is the same answer, in a form a program can read. Same publishing motion as Pattern 1, same storage, same cost — pennies — and nothing on the request path that can fall over.

It often costs almost nothing to start, because Pattern 3 already built it. The nightly export that feeds the finance system can drop one more copy — the public fields only, chosen deliberately — into the public bucket. The habit the agency already has becomes the interface the public gets.

Software teams call the formal version of this an API — a defined doorway where one program asks and another answers, live. A published file is the smallest, sturdiest first step down that road. It is not real-time; the data is as fresh as the last publish. But it has the three things a consumer of data actually needs first: a stable address, a known shape, and a schedule that gets kept. A program can build on that. Nobody can build on a records-request queue.

The path onward runs in small steps, each useful on its own: publish the files, document what each field means, keep the schedule religiously, and add a live doorway later — only where freshness genuinely earns its cost.

A yardstick that already exists

None of this is new thinking. In December 2007, thirty open government advocates gathered in Sebastopol, California and wrote down eight principles of open government data that still hold up. Open government data, they said, is:

  1. Complete — all public data is made available, in bulk, not just slices of it.
  2. Primary — as collected at the source, not aggregated or reworked.
  3. Timely — released quickly enough to preserve its value.
  4. Accessible — on the open web, retrievable by people and by automated tools alike.
  5. Machine processable — structured data, not free-form text or pictures of text.
  6. Non-discriminatory — available to anyone, with no registration required.
  7. Non-proprietary — in formats no single company controls.
  8. License-free — public data clearly marked as free to use.

They added one more condition: compliance must be reviewable — a named contact who answers, and real recourse when the principles are not met.

Worth noticing: the group’s own annotations say bulk data should be published before fancier interfaces are built, because even the simplest analysis needs the whole dataset, and a live doorway typically returns only slices. So the published-file pattern above is not a compromise on the way to open data. It is where open data starts — and the principles are a checklist an agency can hold its feeds against, one file at a time.

The question to ask: what data do staff repeatedly export by hand for someone else — and what would it take to publish it on a schedule at a stable address instead?

Working on a civic innovation project?

Whether you're exploring an early idea or deep into planning and need the right technical partner to build and deliver — we can help