ArchitectMind
  1. Home
  2. Tutorials
  3. Book 6 · Databases, APIs & Integration
  4. Volume VII
  5. Integration Styles
Book 6 · Volume VII — Enterprise Integration & Messaging · Topic 1.2

Integration Styles

File transfer, shared database, API and messaging

8 min readStage 3 · Systems8 interview questions
Chapter
Chapter 1 — Enterprise Integration Fundamentals
Prerequisites
Topic 1.1
You will be able to
Describe the four classic integration styles and their mechanics, compare them on timeliness, coupling, encapsulation, availability and volume, implement each in the Spring ecosystem, recognise hybrid approaches such as CDC, and choose the right style for each integration
Covers
File transfer; Database; API; Messaging
On this page
  1. 1. Concept / Definition
  2. 2. Why It Exists
  3. 3. Core Concepts
  4. 4. How It Works Internally — Comparing the Styles
  5. 4A. Deep Dive — Hybrids: CDC and Files over Messaging
  6. 5. APIs / Features / Syntax
  7. 6. Practical Examples
  8. 7. Common Problems & Mistakes
  9. 8. Performance & Production Considerations
  10. 9. Architecture & Design Considerations
  11. 10. Interview Questions & Answers

1Concept / Definition

An integration style is the fundamental mechanism by which two applications share data or behaviour. Hohpe and Woolf identify four.

The four integration styles
Figure 1 — The four integration styles
TOC styleMechanism
File transferOne application writes a file; another reads it later (batch)
DatabaseApplications share a database — reading and/or writing the same tables
APIRemote procedure invocation: one application calls another's interface and waits for a result
MessagingApplications exchange messages asynchronously through a broker
Table 1 — The four TOC styles

2Why It Exists

Integration styles evolved with technology: batch files in the mainframe era, shared databases in client/server, RPC and APIs with distributed computing, and messaging for reliable asynchronous exchange. Each solves problems the previous one created; none is obsolete.

How integration evolved
Figure 2 — How integration evolved

3Core Concepts

3.1 File transfer

File transfer
Figure 3 — File transfer
StrengthWeakness
Simple, universal, tool-supportedHigh latency (batch)
Decoupled in time and technologyErrors discovered late
Efficient for bulk volumesPartial files, format drift
Easy audit (files archived)Hard to guarantee exactly-once import
Table 2 — File transfer trade-offs
JAVA
@Bean
Job importProducts(JobRepository repo, Step importStep) {
    return new JobBuilder("importProducts", repo).start(importStep).build();
}
 
@Bean
Step importStep(JobRepository repo, PlatformTransactionManager tx,
                FlatFileItemReader<ProductRow> reader, ItemWriter<Product> writer) {
    return new StepBuilder("importStep", repo)
            .<ProductRow, Product>chunk(1000, tx)
            .reader(reader).processor(ProductRow::toProduct).writer(writer)
            .faultTolerant().skipLimit(50).skip(FlatFileParseException.class)
            .build();
}

3.2 Database

Shared database integration
Figure 4 — Shared database integration
VariantCoupling
Shared read/write tablesVery high — schema is a shared contract
Read-only views for consumersHigh but controlled
Replicated reporting DBMedium
CDC from the database logLow for consumers (events), schema still observed
Table 3 — Degrees of database integration
StrengthWeakness
Immediate consistency, simple SQLSchema changes break others
No extra middlewareNo encapsulation of business rules
Familiar toolingContention, locking, performance coupling
Table 4 — Shared database trade-offs

3.3 API

API (remote procedure) integration
Figure 5 — API (remote procedure) integration
StrengthWeakness
Encapsulation (data behind interface)Temporal coupling (both up)
Immediate answerLatency chains (Volume VI Ch.5)
Contracts (OpenAPI/proto)Caller must handle retries/failures
Request/response semanticsFan-out to many consumers is awkward
Table 5 — API trade-offs

3.4 Messaging

Messaging integration
Figure 6 — Messaging integration
JAVA
@Service
class OrderEvents {
    private final KafkaTemplate<String, OrderPlaced> kafka;
 
    void publish(Order o) {
        kafka.send("orders.v1", o.id(), OrderPlaced.from(o));
    }
}
 
@Component
class WmsOrderListener {
    @KafkaListener(topics = "orders.v1", groupId = "wms")
    void on(OrderPlaced e) { wms.createPickList(e); }
}
StrengthWeakness
Temporal decoupling, bufferingEventual consistency
Fan-out to many consumersBroker infrastructure to run
Reliable delivery, retriesDuplicates, ordering, debugging complexity
Near real timeHarder request/reply
Table 6 — Messaging trade-offs

4How It Works Internally — Comparing the Styles

Comparing the styles
Figure 7 — Comparing the styles
CriterionBest style
Bulk nightly volumesFile transfer
Strong immediate consistencyShared DB (with care) or API
Immediate answer neededAPI
Many consumers, decoupled availabilityMessaging
Legacy system only exports filesFile transfer
Table 7 — Selecting by dominant requirement

4ADeep Dive — Hybrids: CDC and Files over Messaging

HybridHowBenefit
CDC (database → messaging)Debezium reads WAL/binlog → Kafka eventsDatabase-owned apps emit events without code change
Claim check (file + message)Large file in S3, message carries referenceMessaging semantics, bulk payload
API + eventsCommand via API, state changes as eventsImmediate response + decoupled propagation
Batch over eventsConsumers aggregate events into periodic loadsReal time where needed, batch downstream
Table 8 — Real landscapes blend styles
JAVA
// Claim check: message carries a reference, not the 2 GB file
record CatalogFileReady(String bucket, String key, long sizeBytes, String sha256) { }
 
kafka.send("catalog.files.v1", new CatalogFileReady("erp-exports",
        "products/2026-09-26.csv.gz", 2_147_483_648L, checksum));

5APIs / Features / Syntax

StyleSpring ecosystem
File transferSpring Batch, Spring Integration SFTP/file adapters, S3 events
DatabaseJdbcClient/Spring Data, database views, Debezium
API@RestController, RestClient, Spring gRPC
MessagingSpring JMS, Spring AMQP, Spring Kafka, Spring Cloud Stream
ContractsOpenAPI (APIs), AsyncAPI (messaging), file specs
Table 9 — Implementation toolkit

6Practical Examples

6.1 Shared database outage

Five applications wrote to a shared customers table. A new index added for one application caused lock contention and slowed all five; a column rename broke two overnight batch jobs. Moving to a customer service with an API plus CustomerChanged events removed shared-schema coupling.

6.2 Files that arrived half-written

An import job read a CSV while the ERP was still writing it, importing 60% of products and deleting the rest as "discontinued". A .done marker file and checksum validation fixed the race.

6.3 Worked example — choosing styles for one landscape

IntegrationStyleReason
ERP → shop product catalogueFile (nightly) + events for price changesBulk + timely deltas
Shop → paymentAPIImmediate answer
Shop → WMS orderMessagingDecoupled, reliable
ReportingDB replica / CDCAnalytical queries
Table 10 — Style per integration

6.4 Worked example — safe file handoff

RuleImplementation
Write to temp name, rename atomicallyproducts.csv.tmp → products.csv
Completion markerproducts.csv.done with row count & checksum
Idempotent importTrack processed file names
Archive and error foldersprocessed/, error/
Table 11 — File transfer done properly

6.5 Worked example — read-only database views

SQL
CREATE VIEW reporting.v_orders AS
SELECT o.id, o.status, o.total_amount, o.currency, o.placed_at
FROM orders o;              -- stable contract; internal tables can change
GRANT SELECT ON reporting.v_orders TO reporting_role;

6.6 Worked example — API vs messaging for the same need

Need: "tell WMS about new orders"APIMessaging
WMS down 10 minutesOrders fail or need retry logicQueued, processed later
Add analytics consumerOrder service must call it tooSubscribe
Need WMS responseImmediateSeparate reply/event
Table 12 — Pick by coupling and response needs

6.7 Worked example — AsyncAPI contract

YAML
asyncapi: 3.0.0
info: { title: Orders events, version: 1.0.0 }
channels:
  orders:
    address: orders.v1
    messages:
      OrderPlaced: { $ref: '#/components/messages/OrderPlaced' }
operations:
  publishOrderPlaced:
    action: send
    channel: { $ref: '#/channels/orders' }

6.8 Worked example — style latency comparison

StyleTypical end-to-end latency
File (nightly batch)Hours
File (15-minute drops)Minutes
CDC → KafkaSub-second to seconds
MessagingMilliseconds to seconds
APIMilliseconds
Table 13 — Timeliness spectrum

6.9 Worked example — database integration exit plan

PhaseAction
1Inventory who reads/writes which tables
2Introduce views/API for readers
3Route writes through owning service API
4Emit events (CDC or outbox)
5Revoke direct table grants
Table 14 — Strangling a shared database

6.10 Worked example — B2B partner integration

Partner capabilityStyle
Modern API platformREST + webhooks
EDI providerEDI files via AS2/SFTP
Small supplierCSV via SFTP
Table 15 — Partners dictate style — adapters absorb it

6.11 Worked example — failure behaviour by style

FailureFileDBAPIMessaging
Receiver downFile waits—Call failsMessage waits
Sender downNo file——No messages
Bad dataBatch rejects/skipsConstraint errors4xxDLQ
Table 16 — Failure semantics differ fundamentally

6.12 Worked example — decision record

SectionContent
ContextWMS needs orders within 1 min, may be down during upgrades
OptionsAPI push, shared DB, messaging
DecisionMessaging via Kafka orders.v1
ConsequencesIdempotent consumer, DLQ, AsyncAPI contract
Table 17 — ADR for integration style

6.13 Worked example — Spring Integration file flow

JAVA
@Bean
IntegrationFlow productFiles() {
    return IntegrationFlow
        .from(Files.inboundAdapter(new File("/data/inbound"))
                   .patternFilter("*.csv"),                    // only completed files
              e -> e.poller(Pollers.fixedDelay(Duration.ofSeconds(30))))
        .filter(File.class, f -> new File(f.getPath() + ".done").exists())
        .split(Files.splitter().markers())                     // line by line
        .transform(ProductCsv::parse)
        .handle(productService, "upsert")
        .get();
}
ElementEIP pattern (Chapter 4)
Inbound adapterChannel adapter
.filterMessage filter
.splitSplitter
.transformMessage translator
Table 18 — File transfer implemented with integration patterns

6.14 Worked example — cost of change per style

Change: add field ecoLabel to productFileShared DBAPIMessaging
Producer effortAdd columnALTER TABLEAdd fieldAdd field
Consumer impactParsers may breakQueries OK, ORMs may breakTolerant readers OKTolerant readers OK
CoordinationSpec updateDBA + all appsContract versionSchema registry check
Table 19 — Evolution costs differ

7Common Problems & Mistakes

  • Shared databases as the default integration mechanism.
  • Files without completion markers or checksums.
  • Synchronous APIs for fan-out propagation.
  • Messaging for everything, including simple queries.
  • Undocumented contracts for files and messages.
  • Ignoring failure semantics of the chosen style.

8Performance & Production Considerations

AspectGuideline
FilesAtomic handoff, validation, idempotent import
DatabaseViews/CDC over shared writes
APITimeouts, retries, contracts
MessagingIdempotency, DLQs, schemas
AllMonitoring and ownership
Table 20 — Operational guidelines

9Architecture & Design Considerations

  • Choose styles per integration with ADRs.
  • Prefer encapsulation (API/messaging) over shared databases.
  • Use hybrids (CDC, claim check) to bridge constraints.
  • Document contracts with OpenAPI and AsyncAPI.

10Interview Questions & Answers

Q1BasicConcept

What are the four integration styles?

Hohpe and Woolf's Enterprise Integration Patterns define four fundamental styles. File transfer: one application writes a file and another reads it later, usually in batches over SFTP or object storage. Shared database: applications integrate by reading and writing the same tables. Remote procedure invocation, today usually a REST or gRPC API: one application calls another and waits for a response. Messaging: applications exchange messages asynchronously through a broker such as Kafka, RabbitMQ or a JMS provider. They differ in timeliness, coupling and failure behaviour, and each solved problems the previous one created. None is obsolete; real landscapes mix all four, plus hybrids such as change data capture and claim check.

Q2BasicTrade-off

What is the main drawback of file transfer?

The main drawback is latency: data moves in batches, often nightly or hourly, so receivers work on stale data and anything that needs near-real-time updates cannot use it. Errors also surface late. A malformed record, a missing file or a half-written file is discovered only when the import runs, possibly hours after the source produced it, and the batch may fail partially. Contracts such as CSV layouts are often undocumented, and duplicates or reprocessing need explicit handling. The strengths are real: simple, decoupled in technology and time, and ideal for bulk volumes and partners with limited capabilities. So the drawback matters when timeliness or early error feedback is a requirement.

Q3IntermediateConcept

Why is shared-database integration risky?

Because the schema becomes a public contract between all applications using it, but nobody manages it as one. Any change, a column rename, a new constraint, even an index, can break or slow other applications, so the schema freezes and every change needs cross-team coordination. Business rules are not encapsulated: each application writes the tables directly, so validation and invariants are duplicated or bypassed, and it is unclear who owns the data. Runtime coupling is high too: one application's heavy query or lock causes contention for all of them, as in this note's outage example. Read-only views or replicas reduce the damage; APIs, events or CDC are the long-term exit.

Q4IntermediateTrade-off

When is an API better than messaging?

An API is better when the caller needs an immediate answer to continue: a price quote, a stock check, a payment authorisation or a validation result, or when a user is waiting for a read. Request-response over REST or gRPC gives the answer directly, with simple error handling and debugging, whereas request-reply over a broker adds correlation ids, reply queues and latency for no benefit. APIs also suit queries over data another service owns when copying it is not justified. The price is temporal coupling: the provider must be available and fast, so callers need timeouts, retries for idempotent calls and circuit breakers. For propagation to many consumers, messaging wins.

Q5Senior EngineerConcept

What does messaging add over APIs?

Messaging adds temporal decoupling: the sender hands a message to the broker and continues, and the consumer processes it when it is available, so an outage or slowdown of the consumer does not fail the sender. The broker buffers load spikes, letting consumers work at their own pace and scale out with partitions or competing consumers. It provides reliable delivery through persistence, acknowledgements, retries and dead-letter queues. Publish-subscribe makes fan-out easy: new consumers subscribe without any change to the producer. The costs are eventual consistency, at-least-once delivery that requires idempotent consumers, ordering concerns and harder end-to-end debugging, so trace context must travel in message headers.

Q6Senior EngineerInternals

What is change data capture and where does it fit?

Change data capture reads a database's own change log, the PostgreSQL WAL or the MySQL binlog, and turns committed inserts, updates and deletes into an event stream, typically with Debezium publishing to Kafka. It is a hybrid of database integration and messaging: the source application keeps writing to its database unchanged, while consumers receive events asynchronously instead of querying shared tables. It fits legacy systems you cannot modify, cache and search-index synchronisation, and strangler migrations. Combined with an outbox table, it gives reliable event publishing without dual writes. Be careful with raw table events: they expose the internal schema, so publish curated domain events through the outbox where possible.

Q7Technical ArchitectDesign

How do you make file transfer reliable?

I make every step explicit and recoverable. The producer writes to a temporary name and renames atomically when the file is complete, then writes a completion marker or manifest containing the record count and a SHA-256 checksum. The consumer processes only files with a marker, verifies the checksum and count, and validates the content against a documented schema before applying anything. Imports are idempotent, keyed by file name or business key, so reruns are harmless, and destructive inferences such as deleting missing products require a complete, validated file. Processed files move to an archive folder and rejected ones to an error folder, with alerts. Spring Integration or Spring Batch implements these patterns well.

Q8Solution ArchitectDesign

How would you choose styles for a new landscape?

I start with an inventory of integration needs rather than a preferred technology. For each integration I record the timeliness required, whether the caller needs an immediate response, how many consumers there are, data volume, coupling tolerance, failure behaviour and any partner constraints. Then I choose per integration: APIs for immediate queries and commands, messaging for propagation and fan-out, files for bulk exchange and constrained partners, and CDC or read-only views as bridges for legacy databases, while avoiding new shared-database integrations. Each choice is captured in an ADR. Finally I standardise one supported platform per style, with contracts in OpenAPI and AsyncAPI, so teams do not reinvent tooling.

Newsletter

Get new tutorials every week

New ArchitectMind tutorials and interview questions, once a week. No spam, unsubscribe anytime.

Almost done! Check your inbox and click the confirmation link to complete your subscription.
Keep going in Book 6

Databases, APIs & Integration

Volume I · Topic 1.1

Why Databases Exist

Database Fundamentals & Relational Data Modeling

Volume I · Topic 1.2

Database Management Systems

Database Fundamentals & Relational Data Modeling

Volume I · Topic 1.3

Database Architecture

Database Fundamentals & Relational Data Modeling

Volume II · Topic 1.1

Data Retrieval

SQL, Transactions, Concurrency & Database Performance

Volume II · Topic 1.2

Data Modification

SQL, Transactions, Concurrency & Database Performance

Volume II · Topic 1.3

Aggregation

SQL, Transactions, Concurrency & Database Performance

Volume III · Topic 1.1

JDBC Architecture

Java Persistence & Data Access Architecture

Volume III · Topic 1.2

PreparedStatement

Java Persistence & Data Access Architecture

Volume III · Topic 1.3

JDBC Transactions

Java Persistence & Data Access Architecture

Volume IV · Topic 1.1

Why NoSQL Exists

NoSQL, Caching & Polyglot Persistence

Volume IV · Topic 1.2

Categories

NoSQL, Caching & Polyglot Persistence

Volume IV · Topic 1.3

Trade-offs

NoSQL, Caching & Polyglot Persistence

Volume V · Topic 1.1

HTTP Architecture

API Design, HTTP & REST

Volume V · Topic 1.2

Methods

API Design, HTTP & REST

Volume V · Topic 1.3

Status Codes

API Design, HTTP & REST

Volume VI · Topic 1.1

Gateway Responsibilities

API Management, GraphQL & Distributed API Design

Volume VI · Topic 1.2

Gateway Patterns

API Management, GraphQL & Distributed API Design

Volume VI · Topic 1.3

Gateway Risks

API Management, GraphQL & Distributed API Design

Volume VII · Topic 1.1

Why Systems Integrate

Enterprise Integration & Messaging

Volume VII · Topic 1.3

Point-to-Point Integration

Enterprise Integration & Messaging

Volume VIII · Topic 1.1

Integration Boundaries

Integration Architecture & Data Consistency

Volume VIII · Topic 1.2

Synchronous vs Asynchronous

Integration Architecture & Data Consistency

Volume VIII · Topic 1.3

Coupling

Integration Architecture & Data Consistency