Section650

Writing

TopicLeadership
Reading14 min

What Building Public-Sector Applications Taught Me About Software Engineering

From startup development to supporting public-sector systems: what I learned about FedRAMP, Authority to Operate, Section 508, Plain Writing, security and building software that must meet government requirements, and why the discipline makes commercial software better too.

By Ka Lun Chan · Engineering leadership · Leadership / Architecture / Engineering judgment

The technology was familiar. Everything around it changed.

After working in software, telecom, startups and engineering leadership, I assumed I had met most of the ways building and running software can be hard. Then I started working on public-sector applications, and it was a different experience, though not because the technology was harder. We were still building web applications, designing APIs, working with databases, deploying infrastructure and troubleshooting production, with the same kinds of frameworks, databases and cloud services I had used elsewhere.

What changed was everything surrounding the software: the security requirements, accessibility, documentation, change management, operational controls, the authorization process, and even how we were allowed to word a message to a user. Building software for the public sector is not only delivering features. You also have to demonstrate that the software is secure, accessible, maintainable and operated according to the requirements that apply to it, and that changed how I approach engineering.

Building public-sector applications teaches an engineer that quality has more dimensions than working code. Security has to be demonstrable, accessibility has to be designed in, communication has to be understandable, changes have to be traceable, operations have to be documented, and risk has to be evaluated continuously. None of those is unique to government, and government is where they stop being optional.

Applications that support public-sector programs

My government work includes systems that support public-sector small business certification programs: applications that help businesses interact with a program, submit information and work through a certification process. I built FedPath, a tool for small businesses finding federal contracts, partly because I had seen how hard those processes are from the inside.

From an engineering seat the challenges are recognizable: complex business rules, several user roles, long application workflows, document management, integrations with other systems, data validation, reporting, and keeping a system current as the program rules change. What government adds is a set of responsibilities that stay invisible in a startup. A change that looks simple in the code may need security review, accessibility validation, documentation and additional testing before it can ship. At first that feels like process for its own sake. Over time I understood what each piece of it was protecting.

A form is rarely just a form

To the business owner filling it in, a certification application looks like a long form. Each question feeds something underneath it. An answer about who owns the business feeds eligibility rules, and ownership is rarely one number. There can be several owners, a parent company, a trust, or a manager who runs the business day to day without owning much of it. Each certification program has its own definitions of ownership and control, and a business can apply for more than one program, so the same answer may be read by different rules.

The answer then decides which documents are required, what a reviewer sees, what the reports count, and what the audit trail has to record. Suppose a program clarifies how it counts ownership held through another company. On the ticket that is one field and a validation message. In the system it touches the eligibility check, the document checklist, the reviewer’s screen, the applications already in progress that were valid under the old rule, the reports that count approvals, the wording that explains the rule, and the accessibility of whatever new input appears.

Finding those paths before anyone writes code is most of the work, and it is why I distrust an estimate given before someone has walked them. The code change may be small. The decision about what happens to the businesses halfway through an application is a program decision, and engineering’s job is to surface it early enough that the right person makes it.

FedRAMP: implementing a control and proving it works

Security was not new to me. My career started with router access control lists, NetScreen firewalls and a managed security service, and it continued through application and cloud security. Government cloud security formalized it to a degree I had not worked under before. FedRAMP, the Federal Risk and Authorization Management Program, is the standardized approach to assessing and authorizing cloud services that federal agencies use.

The lesson that mattered most was the difference between implementing a security control and demonstrating that it operates effectively. It is one thing to say access to production is restricted. It is another to show who has access, how it was approved, how authentication is enforced, how privileged access is controlled, how access is reviewed, how every change to it is recorded, and what happens the day someone leaves. The same applies to logging, vulnerability management, encryption, incident response and configuration management. Security is a set of operational responsibilities as much as a set of technologies, and the responsibilities need evidence.

One distinction is worth being precise about. A FedRAMP authorization covers a cloud service offering within a defined boundary. It does not authorize every application deployed on that infrastructure. The application still carries its own responsibilities and may face additional agency requirements, and designing a government system means knowing which controls you inherit from the platform and which you own.

Authority to Operate: what production-ready means

In commercial software, deploying usually comes down to whether the organization believes the system is ready. In government environments the decision is formal. An Authorizing Official evaluates the system’s risk and decides whether to grant an Authority to Operate, an ATO. The engineering team does not make that decision. It contributes to it, by implementing controls, maintaining documentation, addressing findings and providing technical evidence: system security plans, control assessments, risk assessments, plans of action (POA&Ms) for open findings, configuration management, vulnerability management, continuous monitoring, incident response procedures and contingency plans.

What struck me was how closely that work sits on top of ordinary engineering. A deployment pipeline is no longer only a way to ship code. It is the record of what changed, when and by whom. Logging is no longer only for troubleshooting. It supports auditability, security investigations and continuous monitoring. Infrastructure configuration is no longer only a DevOps concern. It is part of the system’s documented security posture. Production readiness means more than the application working. It means the organization can show that the risks are understood and managed, and the engineering has to produce that showing as a by-product of doing the work well.

Section 508: accessibility is an engineering responsibility

Section 508 requires covered federal information and communication technology to meet applicable accessibility standards, which for web applications means the Web Content Accessibility Guidelines at the required level. In practice it means designing for how people with disabilities use the system, which a development team focused on whether a feature looks right will miss. We need to check screen-reader and keyboard operation, field labels, error messages and contrast. A long workflow also needs to be usable without relying on visual cues. Those checks affect both the design and the implementation.

A certification application makes it concrete. A business owner completes a long form, uploads documents, reviews the information and submits. If a validation error is only red text, some users never learn what went wrong. If a custom dropdown ignores the keyboard, some users cannot complete the form at all. If focus is not managed when a modal opens, a screen reader user loses their place. A feature can pass every functional test and still be inaccessible, which is why accessibility belongs in design, implementation, testing and the acceptance criteria. Automated tools catch some of it; keyboard and assistive-technology testing by a person catches the rest. I treat it as part of software quality throughout development. Modernizing public-sector applications covers carrying those checks into every release of a replacement.

Plain Writing: the hardest problem wasn’t technical

The requirement I find most interesting is Plain Writing. Federal agencies have a responsibility to communicate clearly with the public, and the Plain Writing Act and the guidance around it ask for communication people can understand and use. For a government application that is not decoration. Imagine a small business owner applying for a certification who does not know the difference between an eligibility requirement, supporting documentation, a certification decision and a program-specific rule, and the interface explains itself in legal and administrative language. The software can work perfectly and the person still cannot finish. That is a product problem, and usually an engineering problem too, because the words come out of the code.

Government applications carry complex business rules, and the user should not have to understand the implementation to complete a task. Instead of exposing internal terminology, the interface should say what to do next. “Validation failed due to missing required documentation” is accurate and useless. “Upload your ownership document before continuing” is actionable, provided the wording reflects the program’s actual requirement, which it has to. Complex rules do not require a complicated experience, and the best software I have shipped for startups and consumers followed the same principle: help people understand what to do next.

Security controls shape the architecture

Government security requirements reach into architecture, and access control is the clearest case. A typical application starts with a few roles. A government system may need permissions by program responsibility, organizational boundary and specific action: who can view an application, who can edit it, who can approve or reject it, who can open a sensitive document, who can export, and what happens when someone’s responsibilities change. Those decisions land in backend authorization, API design, database access and frontend behaviour at the same time.

Authentication tells the system who is signed in. Authorization decides what that person may do with this application, this document and this field, and it is where most of the design work sits. The data is the reason it matters. A certification application can hold ownership details, financial statements, tax returns and personal information about the owners, and a business owner who uploads those is trusting that only the people who need them will see them.

Hiding a button in the interface does not stop anyone from calling the API. Authorization is enforced on the server, on every request, against the specific record, the point I made in API architecture lessons. Every endpoint is a front door, and the frontend is only one of the clients that can knock on it. Least privilege applies to the system as much as to people: a reviewer sees the applications assigned to their program, a service account reads the storage it needs and nothing else, and access to production data is the exception, with a record of who asked and why.

Audit logging asks its own questions: which actions must be recorded, what each record captures, and how the records are protected from the people they describe. A useful entry says who did what to which record, when, and what changed, and it lives where the person acting cannot edit it. Those records are also security evidence. When an assessor asks how you know only authorized people changed an application’s status, the answer should be a query someone can run. Security requirements are never isolated tasks on a backlog. They shape the system.

External systems will surprise you

Public-sector applications rarely stand alone. They exchange data with other government systems, accept sign-ins from an external identity provider, and pass results on to systems run by other teams. Each of those is a dependency with its own release schedule, its own priorities and its own idea of what a valid response looks like. The integration you tested last month is not guaranteed to behave the same way this month.

So we designed for the other system behaving unexpectedly, because eventually it will:

  • Validate what comes back before trusting it: the shape, the types and the values you depend on. A response that parses is not necessarily a response you can use.
  • Treat missing data as missing. In an eligibility workflow, “no data” and “no” lead to different outcomes. A field that silently defaults to empty or zero can turn an outage into a wrong decision about someone’s business.
  • Make authentication failures loud. Credentials and certificates expire and get rotated. A failed sign-in to a partner system should alert someone, not look like an empty result.
  • Time out, retry within limits, and make retries safe, so a slow dependency doesn’t tie up the application and a retry can’t submit the same thing twice.
  • Record what the other system returned and when. Months later a reviewer may need to know why an application showed what it did, and “the other system said so” only helps if you kept what it said.
  • Tell the user plainly when a dependency is down, what it means for them, and that their work is saved.

Testing follows the same assumption. Contract tests against recorded responses catch changes in the shape of the data. Test environments for external systems often differ from production in data and availability, so the plan has to say what can be tested where and what will only be confirmed after release. Defensive programming here is an honest reading of the situation: the other system will change, and it won’t always tell you first.

Security doesn’t end at deployment

A system that was secure the day it was authorized becomes vulnerable if nobody maintains it. Software changes, dependencies acquire vulnerabilities, configurations drift, new threats appear, and users join and leave. Continuous monitoring is how an organization notices and responds, and from an engineering seat it means vulnerability scanning, dependency management, infrastructure monitoring, security logging, access reviews, configuration assessment, patching, incident response and tracking remediation to closure.

That work has to fold into normal engineering operations. Treated as a separate function, security becomes a bottleneck and a source of surprises. Considered throughout the development lifecycle, it becomes routine. That is why I value automation: automated tests, dependency checks, infrastructure validation and deployment controls make the security work consistent and leave a trace. Automation does not replace review or judgment. It removes the repetitive part and makes the evidence a by-product. On my teams, vulnerabilities are monitored and fixed as high-priority work, in government and out of it.

Documentation and change management

The biggest adjustment is documentation and change management. In a startup, a feature is requested, someone writes it, it is reviewed, and it ships. Government environments may add steps depending on the authorization boundary, the change classification, the contract and the agency’s procedures: a security impact analysis, formal approval, documentation updates, additional testing. When the change is small, that is frustrating. The purpose is to reduce risk and keep accountability, and once you have seen what an untraceable change costs in a system people depend on, the purpose is easier to respect.

It also changes what “done” means. A working feature and a feature that can be approved and operated are different deliverables. The second one comes with tests that cover the accessibility and authorization paths, a note on its security impact, updated documentation, a way to roll it back, and monitoring that will show whether it behaves in production. Teams that plan only for the first one discover the second at the end of the sprint, and that is a large part of why government delivery has a reputation for being slow.

The leadership challenge is making those processes effective without manufacturing bureaucracy. Too little process, and an untraceable change lands in a system people depend on. Too much, and engineers start batching changes to avoid the overhead, which makes each release bigger and riskier, the opposite of what the process was for. A process nobody understands or follows improves nothing. Each step should answer a specific risk. If nobody can name the risk, the step is a candidate for automation or removal, through the agency’s change process rather than around it. The target is requirements that are clear, automation for everything that can be automated, and controls that address real risks rather than ceremonial ones. I wrote about the general version of this tradeoff in when process helps an engineering team.

What it taught me about leadership

Most of my career was spent where speed and flexibility were essential, and startups still need to deliver fast with little. Government work adds accountability, accessibility, security and operational control. I have learned the two are not opposites. You can build efficiently with strong engineering discipline, and it takes planning: security requirements identified early, accessibility in the acceptance criteria, documentation that evolves with the system, testing that covers the non-functional requirements as well as the functional ones, and a team that understands why each requirement exists.

As an engineering leader I see my job as helping developers work within those constraints, which means explaining what problem a process solves rather than announcing another process. Engineers who understand the purpose implement the requirement well and find the ways to make the workflow lighter. The ones who were only told to comply do the minimum and resent it, and the system is worse for it. I wrote about how I try to run that conversation in how I run engineering.

A few habits did more than anything else to keep delivery steady in that environment:

  • Write the non-functional work into the acceptance criteria. Keyboard and screen-reader behaviour, who may see the record, what gets logged and how a message reads to a business owner belong in the story, so nobody discovers them in review.
  • Keep changes small. A small change is easier to review, easier to assess for security impact, easier to approve and easier to roll back. That matters more when every release passes through a change process, and it is the same argument I make in smaller user stories and pull requests.
  • Name risks early: an integration nobody has tested against, a rule the program hasn’t settled, a control nobody owns. Surprises are cheapest in week one, and in a regulated system they get expensive quickly.
  • Coordinate across teams. Security reviewers, accessibility testers, program staff, other contractors and the teams that run the systems we integrate with all have their own schedules. Knowing who needs to see a change, and when, is part of the plan.
  • Bring options along with the problem. When a requirement collides with a date, leadership needs the choices, what each costs and a recommendation. “We’re blocked” gives them nothing to decide.
  • Deliver predictably. Stakeholders trust a team that ships what it said it would and raises problems before the deadline. That trust is what buys room to push back when a request would add risk.

The requirements, on one page

The whole thing fits on one page once you see it as a cycle with three kinds of actor: the agency, which decides; engineering, which builds and supplies the evidence; and the monitoring that runs after authorization and feeds the next assessment. The figure is simplified from the NIST Risk Management Framework, and the step where most engineers first meet it, Implement, is only one of six.

Fig. 688-1 How a government system gets authorized, and stays authorizedSimplified from the NIST Risk Management Framework. Select a step, or walk the cycle with Next. Steps where engineering does the work are marked.

Framework

FIPS 199, NIST SP 800-60

Engineering supplies

System boundary, the data it handles, architecture diagrams

Beyond FedRAMP, the ATO, Section 508 and Plain Writing, an engineering team on a government system works inside a wider set of frameworks. Which ones apply depends on the agency, the system boundary, the data and the contract, and the authoritative text is at FedRAMP, NIST, Section508.gov and PlainLanguage.gov rather than in any blog post. The table is the map I keep in my head.

Fig. 688-2 Government requirements an engineering team meets, and why each exists. Which apply depends on the agency, the system boundary, the data and the contract.
Framework or requirementWhy it matters
FISMAFederal information security governance and risk management
NIST Risk Management Framework (SP 800-37)The structured process for categorizing, selecting, assessing and authorizing
NIST SP 800-53The catalog of security and privacy controls
NIST SP 800-60 and FIPS 199 / 200Categorizing a system and its minimum security requirements
FedRAMPStandardized assessment and authorization of cloud services used by agencies
Authority to OperateThe formal decision that a system’s risk is understood and accepted
Section 508 and WCAGAccessibility of government digital services
Plain Writing ActCommunication the public can understand and use
Privacy Act and privacy impact assessmentsPrivacy protections where personal information is handled
Records managementRetention and disposition of government records
Continuous monitoringOngoing assessment of security posture after authorization
Supply chain security and secure SDLCDependencies, third-party risk and security built into development
OMB digital experience guidanceUsability and accessibility expectations for public-facing services

Still learning

Public-sector work made me more deliberate about documenting decisions and demonstrating that controls operate as intended. My earlier operations experience helped me recognize the value of those records when a system changes hands or something fails.

Those disciplines are not only for government. A startup does not need an authorization process, and it still benefits from good access control, accessible interfaces, clear documentation and reliable deployment. The skill is applying the level of rigor the system’s risks and the business actually call for. What I would take from public-sector work into other environments:

  • In a startup, enforce authorization on the server against the record, and keep an audit log, from the first version. Both are cheap early and painful to retrofit after the first enterprise customer asks.
  • In a SaaS company, treat every integration as a dependency that will change. Validate responses, time out, retry safely and record what came back.
  • On an enterprise platform, before estimating a “small” change, map which workflows, reports and records it touches.
  • In a regulated environment, plan the evidence with the feature and let the pipeline produce it, so compliance is a by-product of delivery rather than a project at the end.

Writing the code is one part of the job. The rest is making the system secure, maintainable, reliable and understandable, and suited to the people who depend on it. Government work made that harder to forget, and it is what I will carry into whatever I build next.

Short answers

What is the difference between FedRAMP and an Authority to Operate?

FedRAMP is the standardized program for assessing and authorizing cloud services that federal agencies use, and its authorization covers a cloud service within a defined boundary. An Authority to Operate is the formal decision by an agency’s Authorizing Official that a specific system’s risk is understood and accepted. An application on a FedRAMP-authorized platform still needs its own controls, evidence and authorization.

What does an engineering team contribute to an Authority to Operate?

Implemented controls and the evidence that they work: system security plans, control assessments, risk assessments, plans of action (POA&Ms) for open findings, configuration and vulnerability management, continuous monitoring, incident response procedures and contingency plans. The Authorizing Official makes the decision; engineering makes it possible.

Why is Section 508 an engineering responsibility rather than a design one?

Because a feature can pass every functional test and still be unusable with a screen reader or a keyboard. Labelled fields, understandable validation errors, sufficient contrast, keyboard-operable controls and correct focus management are implemented in code, tested by people as well as tools, and belong in the acceptance criteria.

How should a public-sector application handle external government system integrations?

Assume the other system will change or fail without warning. Validate responses before trusting them, treat missing data as missing rather than as a default value, alert on authentication failures, time out and retry safely, record what the external system returned, and tell users plainly when a dependency is unavailable. Contract tests against recorded responses catch changes in the data’s shape.

Do government engineering disciplines apply to commercial software?

Yes, at the right level of rigor. A startup does not need an authorization process, and it still benefits from server-side access control, accessible interfaces, clear user communication, traceable changes and reliable deployment. Security has to be demonstrable, accessibility designed in, and risk evaluated continuously, wherever people depend on the system.

What I carry into other work

Public-sector applications made me more deliberate about security evidence, accessibility and the records we keep of a change. Those requirements affect how the team builds the software from the start.

Plan for the evidence from the first sprint, and make sure the team knows why each control exists.

That is how I lead engineering in regulated environments, and the same discipline, at the right level of rigor, makes commercial software better too.

Modernizing public-sector applications