Older tools can return because the work has changed

Senior engineers who spend their days maintaining connections between third-party services have a reason to reconsider an integrated framework: its shared components can leave them more time for business logic. Similar reassessments can favor a monolith that keeps application functionality together, direct access through SQL, a language for working with data in tables, or a local development environment. These choices can reduce the complexity a team manages, even when they also limit its architectural freedom.

Such returns are part of how software develops. Progress comes through deliberate improvement, opportunities to reuse existing work, and technical challenges pursued to discover what is possible. Along the way, older ideas find new uses because surrounding tools have changed or teams better understand their maintenance costs.

The practical question is who will carry the work each choice creates. Across nine apparent reversals in architecture, languages, infrastructure, and staffing, some technologies take on more responsibility for developers, while others offer control worth maintaining. The engineer keeping other companies’ services connected gives us a concrete place to begin.

Integrated frameworks can take responsibility for connections

For that engineer, connecting services is an ongoing development duty. The application must keep working as providers change their interfaces and tools, so developers must maintain those connections alongside the application’s own behavior. That maintenance competes for time with the business logic that makes the application useful.

The original reason for assembling specialized services was sound: teams could reuse established capabilities instead of building an entire system themselves. Jamstack, an approach based on JavaScript, application programming interfaces (APIs), and markup, and the modern data stack, which combines specialized cloud-based data-management tools, follow this approach. Over the last several years, enthusiasm for renting capabilities encouraged teams to choose a strong tool for each requirement.

An application built from a dozen software-as-a-service platforms shows what those choices involve. One platform supplies authentication, another the database, another search, and another hosting, while further services handle other functions. Developers choose the platforms, connect them through APIs, and write the code that makes independently designed systems cooperate.

The services are rented, but the team owns the connecting code. When a provider changes its software development kit, or SDK, developers must adapt their integration and preserve the application’s behavior. As more services change independently, a choice that reduced internal feature development can create substantial internal maintenance.

Integrated frameworks take on some of that work through shared conventions about how components fit together. Rails and Django established the “batteries included” approach, while Next.js and Spring Boot offer integrated foundations for application development. Developers accept the framework’s preferred arrangements so it can provide connections they would otherwise maintain.

Within those conventions, developers use supporting components such as NextAuth or Spring Security and connect an external database or authentication provider where needed. Next.js and Spring Boot can therefore organize an application without supplying a proprietary database. Following this “golden path” trades some freedom for fewer integration decisions and less custom connecting code, an exchange that becomes attractive after years of maintaining multiple vendors’ services.

Okoone experts
LET'S TALK!

A project in mind?
Schedule a 30-minute meeting with us.

Senior experts helping you move faster across product, engineering, cloud & AI.

Please enter a valid business email address.

Service and database boundaries need to earn their place

Framework conventions address connections within an application; service architecture determines which connections must cross a network. Microservices divide an application into separately operated services and are powerful when requirements justify them. But adopting them by default can leave a team debugging Kubernetes, a system for managing containerized applications, and coordinating distributed components before the problem requires that work.

Network boundaries also affect execution because calls between services incur network latency. A monolithic server keeps functionality together, avoiding the particular network calls and distributed operations introduced by splitting it into microservices. Removing unnecessary distribution produces the benefit; the age or popularity of either design has no bearing on it.

Keeping functionality together still requires careful internal design. A poorly structured monolith can become overwhelmingly complex, while requirements for high availability and other aspects of quality of service, meaning reliable and consistent operation, add moving parts. Separating data, service, and user-interface responsibilities can nevertheless give developers a simpler model of how the application works.

That internal structure can coexist with remote applications built by the organization or supplied by third parties. A central server stack leaves room for those services wherever they meet a requirement. The design process starts with the required behavior, finds the minimum complexity that can deliver it, and chooses the arrangement with the least avoidable operational burden. Some teams will reach microservices through that process; others will retain a monolith.

The same test applies to the layer between an application and its database. SQL, invented in the 1970s, helped support the internet’s expansion alongside other foundational technologies. Its lasting value comes from the relational model, which provides a rigorous and broadly useful way to organize and manipulate information.

Relational information processing remains a basic application need, giving SQL a different position from an older language such as COBOL. NoSQL databases and other data-management approaches also have legitimate uses. Renewed interest in SQL concerns how directly developers can express the operations their applications need and how much structure those operations should require.

Structure can help precisely because it imposes constraints. Defining and following a database schema, a description of the data’s organization, gives the application a stable basis for handling information. Those constraints reduce uncertainty about what the rest of the system receives.

SQL is also gaining execution options through WebAssembly, or Wasm, a portable binary format that a runtime executes. Running SQL in a browser brings a familiar way of processing data to the client side of the network. An older data model gains a new role because another technology changes where it can run.

On the server, JOOQ offers a simpler wrapper that preserves more direct SQL access than an object-relational mapping layer, or ORM, such as Hibernate. An ORM translates between application objects and relational data, adding useful capabilities alongside another abstraction developers must understand. Counting layers alone therefore makes a poor design test: a wrapper earns its place when the effort it saves justifies the concepts and constraints it introduces.

Mature languages can absorb capabilities associated with challengers

An abstraction’s value can also change as a language takes on more work itself. JavaScript and Java show two distinct paths: incorporating ideas associated with a challenger and moving execution management into the runtime. In both cases, the question is what the language now enables developers to do.

TypeScript attracted individual programmers and enterprises by adding types to JavaScript. Its appeal encouraged the expectation that it could eventually absorb the internet’s entire JavaScript codebase. Now another direction is emerging: JavaScript accommodates useful TypeScript-inspired behavior while remaining the language that executes.

One proposal, “types as comments,” would let JavaScript accept type annotations without giving them a role in runtime execution. A related direction places more checking in the integrated development environment, or IDE, where linting flags potential problems while a developer works. Type information can thus help at different stages of development.

Runtime support for “type stripping,” including in Node.js, changes the path to execution more directly. The runtime replaces type annotations with blank space and runs the remaining JavaScript. For code handled this way, removing the annotations no longer requires a separate compilation step, reducing workflow friction.

Together, these developments point toward TypeScript becoming an increasingly sophisticated checking tool for JavaScript. Developers may keep type-related assistance while simplifying the route from editing code to running it. Checking and annotation removal can happen at different points without requiring the entire workflow to move into a separate language toolchain.

Java’s evolution addresses a different burden: concurrency, or managing multiple activities during overlapping periods. Java has long had a reputation for verbosity, boilerplate, and slow change, while Node.js became associated with asynchronous input and output, Go with lightweight concurrency, and Rust with speed. Requiring public static void main for a small program captures that ceremony.

Virtual threads and related structured-concurrency upgrades give the Java Virtual Machine, or JVM, more responsibility for scheduling and managing concurrent work. Virtual threads are lightweight threads managed by the JVM, while structured concurrency organizes related tasks so their lifetimes can be managed together. Developers can therefore leave more execution management to the platform.

Virtual threads can potentially support millions of parallel requests on a Java server, with adoption characterized as requiring a single import change. Compatibility with older thread APIs also lets the newer concurrency model work through existing programming interfaces. These capabilities give a language invented in the 1990s a different appeal from the one its longstanding reputation suggests.

The change underlies the forecast that thirty-year-old Java could become a must-try language in 2026. Its relevance depends on the concurrency work the platform can take on and how well that capability fits an application. JavaScript’s typing directions address a different problem, but both developments change the work left to application developers.

Local and owned infrastructure can make control worth the work

Moving work into a language or runtime leaves another decision open: where development and execution should happen. Local development environments, owned infrastructure, and portable execution offer different forms of control. Their benefits depend on which resources a team wants to manage and which duties it can support.

Cloud development environments seem a natural successor to local IDEs because they move more setup away from a developer’s machine. Yet ownership, the “buy versus rent” decision, and the personal nature of a working environment all help explain the continued preference for local tools. Developers can value direct control over an environment they use throughout the day.

Local machines also support rapid iteration. Even a modest business laptop can keep much of the development environment in its own random-access memory (RAM) and solid-state drive (SSD) storage, producing almost immediate results. Remote AI services can remain part of that workflow, allowing developers to use an AI back end for assistance while keeping most activity on their machines.

Control carries a larger operational cost when an organization owns the infrastructure running its applications. Larry Ellison’s historical ridicule of cloud enthusiasm as a fad came from a commercially interested position: his company, Oracle, sells infrastructure technology and cloud services, so its business benefits from customers’ infrastructure choices. His criticism sits alongside cloud computing’s substantial benefits; the choice still depends on the organization’s work.

For some organizations, that work favors running compute, storage, networking, or a combination of them in-house. Internal expertise can make the equipment manageable, while cost control, predictable billing, and data sovereignty, the ability to keep data under the required jurisdiction and control, can make ownership attractive. Those benefits must be weighed against the responsibility for provisioning and managing the resources.

Ownership therefore limits the idea that better technology always removes work. A team may reasonably accept more operational duties because it can manage them and values the control they provide. The governing question remains “What’s the right tool for the job?”

Portable execution raises a further question: how much must an environment carry with it? Docker’s influential proposition was to package software and its dependencies into a portable unit deployable across environments. That portability remains useful, although configuration files and the concepts developers must learn can become cumbersome because Docker adds an abstraction between software and its environmental requirements.

Wasm takes a different approach to portable execution. Code is compiled into a portable binary that a runtime executes, with low overhead as a design goal. Some runtimes compile that binary further into machine code, changing how the program ultimately runs.

The execution environments help explain the difference in overhead. Docker starts a Linux user space, the operating-system environment available to applications, and a virtualized file system, while Wasm runtimes aim to keep the execution environment small. Wasm’s appeal follows from that lighter model, though the capabilities a deployment needs still shape the choice.

Docker’s established enterprise role and extensive supporting tools give teams practical reasons to keep using it. Meanwhile, Wasm is moving beyond experimentation toward more consequential uses. As with a local IDE connected to remote AI, organizations can adopt the newer capability while retaining an existing tool for the work it already handles well.

Broad engineering judgment helps teams assign responsibility

These combinations leave people responsible for deciding how the parts fit together. A full-stack job description can accumulate enough duties to resemble an entire IT department, making mastery of every listed specialty unrealistic. Leaders need to connect technology choices with the expertise required to maintain them.

A decision discussion can begin with five questions, asked in sequence. What requirement does the choice satisfy? What work does it remove from developers, and what work, constraints, or operational duties does it introduce?

The final two questions connect those duties to the team. Can the team support them? Would a hybrid arrangement meet the requirement with less avoidable complexity? Answering them makes staffing part of the technical decision, because every connection, service boundary, and owned resource needs someone able to maintain it.

That ability depends on knowledge people can keep ready for use. Maintaining detailed command of CSS grid layout, which arranges web-page content in rows and columns, competes with keeping database-design knowledge immediately available, even for an engineer experienced in both. Breadth of experience can improve judgment without producing equal depth across every specialty at the same moment.

Recognizing those limits lets an engineer choose appropriate help. Another person, an AI agent, or a library can provide knowledge or functionality the application needs. Combining those contributions into a working stack remains an engineering responsibility because someone must understand their dependencies and decide where deeper expertise is necessary.

Senior experience strengthens that judgment across technologies. “Full-stack” competence can describe the ability to assess relationships, combine components, and identify where specialist help is needed. Leaders can give that engineer system-level responsibility while relying on colleagues and tools for deeper expertise, with clear ownership of the work delegated to each.

Key takeaways for leaders

  • Reduce integration maintenance: Engineering managers evaluating integrated frameworks need to account for the cost of maintaining connections between vendors. Shared conventions can free developers to focus on business logic, while limiting some architectural choices.
  • Make service boundaries earn their place: Architects evaluating microservices need a requirement that justifies their network latency and operational overhead. A well-structured monolith can simplify delivery when separate services add avoidable complexity.
  • Reassess database abstractions: Database teams evaluating SQL wrappers and object-relational mapping layers need to weigh the effort each saves against the concepts it introduces. Direct SQL access and schema constraints can provide a simpler, stable foundation for application data.
  • Review the JavaScript toolchain: JavaScript teams adopting type stripping can remove a separate compilation step for supported code while retaining type checking elsewhere in the workflow. Evaluate runtime support and checking needs before changing the build process.
  • Revisit Java for concurrent workloads: Java platform teams evaluating virtual threads and structured concurrency have an opportunity to move more execution management into the JVM. Assess these capabilities against the application’s workload and existing interfaces.
  • Preserve useful local control: Development managers comparing local and cloud environments need to include iteration speed and developer control in the decision. Local IDEs can support fast workflows alongside remote AI assistance.
  • Price the responsibility of infrastructure ownership: Infrastructure owners weighing in-house resources against cloud services need to include staffing, provisioning, and ongoing management. Predictable billing, cost control, and data sovereignty can justify those duties where internal expertise is available.
  • Match portable execution to deployment needs: Platform teams evaluating WebAssembly gain a potentially lighter execution environment, while Docker offers established tooling and enterprise support. Compare required capabilities and operational effort before choosing either approach.
  • Staff for system-level judgment: Engineering leaders defining full-stack roles need clear ownership of dependencies and access to specialist expertise. Senior engineers add value by combining components, identifying knowledge gaps, and deciding where colleagues, libraries, or AI assistance fit.

Alexander Procter

November 9, 2026

13 Min

Okoone experts
LET'S TALK!

A project in mind?
Schedule a 30-minute meeting with us.

Senior experts helping you move faster across product, engineering, cloud & AI.

Please enter a valid business email address.