Why architecture matters here

Coprocessor architecture matters because it is the only way to run custom logic where the data lives. Without coprocessors, custom logic runs client-side: read data over the network, process it, write back over the network. For anything volume-heavy (secondary indexes, aggregations, access checks), this is 10-100x slower than server-side.

Cost matters. A well-designed secondary index via coprocessor updates atomically with the primary write; a client-side one requires two-phase logic and can drift. The right architecture directly translates to fewer bugs and lower ops burden.

Reliability is a real concern. A buggy coprocessor can crash the RegionServer or corrupt data. Isolation, exception handling, and staged rollout make coprocessors safe; without discipline they become the source of production incidents.

Advertisement

The architecture: every piece explained

Walk the diagram top to bottom.

Client. Standard HBase API: Put, Get, Scan. Client is unaware of coprocessors on the server side (except for Endpoint invocations).

RegionServer. Hosts regions. Coprocessors run within the RegionServer JVM.

Coprocessor Host. The RegionServer subsystem that loads coprocessor JARs, instantiates them, and dispatches events to them. Isolates each coprocessor's classloader.

Observer. Event-driven hooks. Implement RegionObserver, MasterObserver, WALObserver, or others. Methods like prePut, postPut, preGet fire before or after core operations. Example: intercept Put to update a secondary index.

Endpoint. RPC extension. Define a new gRPC/protobuf service; RegionServer exposes it. Clients call it directly. Example: server-side row count that scans without moving data.

Access Control. Ranger and Apache Sentry use prePut/preGet observers to check permissions. Requests without permission fail server-side.

Secondary Index. Observer on Put maintains a secondary index table atomically. Reads then use the index to find rows in the primary table.

Aggregation. Endpoint that scans local regions and returns aggregates (SUM, COUNT). Reduces client-side data movement.

Loading Options. System-wide (all tables), per-table (via table descriptor), or on-demand (via HBase shell). Choose based on scope.

Isolation + Safety. Each coprocessor loads with its own classloader. Exceptions in observers can either propagate (fail the operation) or be swallowed (log-only). RegionServer restart clears coprocessor state.

ClientPut / Get / ScanRegionServerhosts regions + coprocessorsCoprocessor Hostloads + isolatesObserverpre/post hooks on opsEndpointcustom RPC methodsAccess ControlprePut permission checkSecondary Indexsync index on writeAggregationserver-side sum/countLoading Optionssystem-wide vs table-levelIsolation + Safetyown classloader, exception guardApache Ranger + Phoenix both use coprocessors extensively
HBase coprocessors: Observer hooks fire before/after operations; Endpoints add custom RPC methods; used for access control, secondary indexes, and server-side aggregation.
Advertisement

End-to-end Put and Endpoint flow

Trace a Put. Client sends Put row_key="user-42" col:name="Alice" to RegionServer.

RegionServer receives, routes to the target region. Coprocessor host runs prePut observers in order:

(1) Access control observer: check that the requesting user has Write on this column family. Look up in Ranger cache. Ok.

(2) Secondary index observer: read the current row (if exists) to see the previous name; if changed, prepare a delete of the old index entry and an insert of the new. Execute atomically with the primary Put via a transaction primitive.

(3) Any custom observers: audit log, replication marker, etc.

Core Put executes: append to WAL, insert into MemStore.

postPut observers run: cache invalidation, metrics update, replication publisher.

Ack returns to client.

An aggregation via Endpoint: client calls the AggregationClient with a scan spec. The client's protobuf message goes to every RegionServer hosting relevant regions. Each RegionServer runs the Endpoint code: scan local regions, compute local sum, return. Client sums the per-region sums. No raw rows moved across the network.