Skip to main content Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill cqrsLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Plus depuis ce dépôt Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
Métiers associés SOC
Basé sur la classification professionnelle SOC
name cqrs description Command Query Responsibility Segregation — separate read/write models, event buses, and projections. layer utility category architecture triggers ["cqrs","command query","read model","write model","projection"] inputs ["CQRS architecture decisions","Read/write model separation design","Event bus and projection setup","Eventual consistency strategies"] outputs ["CQRS architecture with separate models","Command and query handlers","Event bus configurations","Projection and read model patterns"] linksTo ["event-sourcing","message-queues","microservices","database-optimization"] linkedFrom [] preferredNextSkills ["event-sourcing","message-queues","microservices"] fallbackSkills [] riskLevel medium memoryReadPolicy selective memoryWritePolicy none sideEffects []
CQRS Patterns
Purpose
Provide expert guidance on Command Query Responsibility Segregation (CQRS) — separating read and write models, implementing command/query buses, building projections, handling eventual consistency, and knowing when CQRS is (and is not) appropriate. Covers both simple CQRS (separate read/write repos) and full CQRS with event sourcing.
When to Use CQRS
Good fit:
Read and write workloads have vastly different scaling needs
Complex domain logic on writes, simple reads
Multiple read representations of the same data (list view, dashboard, search)
Event sourcing is already in use
Microservice with distinct read/write patterns
Bad fit:
Simple CRUD with no complex business logic
Small-scale app with uniform read/write patterns
Team unfamiliar with eventual consistency tradeoffs
Architecture Overview
┌──────────┐ Command ┌─────────────┐ Events ┌─────────────┐
│ Client │ ─────────────→ │ Write Side │ ─────────────→ │ Event Bus │
│ │ │ (Commands) │ │ │
│ │ Query ├─────────────┤ ├─────────────┤
│ │ ←───────────── │ Read Side │ ←───────────── │ Projections │
│ │ │ (Queries) │ │ │
└──────────┘ └─────────────┘ └─────────────┘
Write DB Read DB(s)
Command Side (Write Model)
Command definition:
interface Command {
readonly type : string ;
readonly timestamp : Date ;
readonly metadata : { userId : string ; correlationId : string };
}
interface CreateOrderCommand extends Command {
: ;
: {
: ;
: <{ : ; : ; : }>;
: ;
};
}
{
: ;
: { : ; : };
}
type
'CreateOrder'
payload
customerId
string
items
Array
productId
string
quantity
number
price
number
shippingAddress
Address
interface
CancelOrderCommand
extends
Command
type
'CancelOrder'
payload
orderId
string
reason
string
class CreateOrderHandler implements CommandHandler <CreateOrderCommand > {
constructor (
private readonly orderRepo : OrderWriteRepository ,
private readonly eventBus : EventBus ,
private readonly inventoryService : InventoryService ,
) {}
async execute (command : CreateOrderCommand ): Promise <string > {
const { customerId, items, shippingAddress } = command.payload ;
for (const item of items) {
const available = await this .inventoryService .checkAvailability (
item.productId ,
item.quantity ,
);
if (!available) {
throw new InsufficientInventoryError (item.productId );
}
}
const order = Order .create ({
customerId,
items,
shippingAddress,
});
await this .orderRepo .save (order);
await this .eventBus .publish (
new OrderCreatedEvent ({
orderId : order.id ,
customerId,
items,
total : order.total ,
createdAt : order.createdAt ,
}),
);
return order.id ;
}
}
type CommandHandler <T extends Command > = {
execute (command : T): Promise <any >;
};
class CommandBus {
private handlers = new Map <string , CommandHandler <any >>();
register<T extends Command >(type : string , handler : CommandHandler <T>) {
if (this .handlers .has (type )) {
throw new Error (`Handler already registered for command: ${type } ` );
}
this .handlers .set (type , handler);
}
async dispatch<T extends Command >(command : T): Promise <any > {
const handler = this .handlers .get (command.type );
if (!handler) {
throw new Error (`No handler for command: ${command.type } ` );
}
return handler.execute (command);
}
}
Query Side (Read Model) Query definition and handler:
interface GetOrderSummaryQuery {
type : 'GetOrderSummary' ;
orderId : string ;
}
interface OrderSummaryDto {
orderId : string ;
customerName : string ;
itemCount : number ;
total : number ;
status : string ;
createdAt : Date ;
}
class GetOrderSummaryHandler implements QueryHandler <GetOrderSummaryQuery , OrderSummaryDto > {
constructor (private readonly readDb : ReadDatabase ) {}
async execute (query : GetOrderSummaryQuery ): Promise <OrderSummaryDto > {
const row = await this .readDb .query (
`SELECT order_id, customer_name, item_count, total, status, created_at
FROM order_summaries
WHERE order_id = $1` ,
[query.orderId ],
);
if (!row) throw new NotFoundException (`Order ${query.orderId} not found` );
return row;
}
}
class QueryBus {
private handlers = new Map <string , QueryHandler <any , any >>();
register<Q, R>(type : string , handler : QueryHandler <Q, R>) {
this .handlers .set (type , handler);
}
async execute<Q extends { type : string }, R>(query : Q): Promise <R> {
const handler = this .handlers .get (query.type );
if (!handler) throw new Error (`No handler for query: ${query.type } ` );
return handler.execute (query);
}
}
Projections Projections transform domain events into read-optimized views:
class OrderSummaryProjection implements EventHandler {
constructor (private readonly readDb : ReadDatabase ) {}
async onOrderCreated (event : OrderCreatedEvent ) {
await this .readDb .query (
`INSERT INTO order_summaries (order_id, customer_name, item_count, total, status, created_at)
VALUES ($1, $2, $3, $4, $5, $6)` ,
[
event.orderId ,
event.customerName ,
event.items .length ,
event.total ,
'pending' ,
event.createdAt ,
],
);
}
async onOrderShipped (event : OrderShippedEvent ) {
await this .readDb .query (
`UPDATE order_summaries SET status = 'shipped', shipped_at = $2 WHERE order_id = $1` ,
[event.orderId , event.shippedAt ],
);
}
async onOrderCancelled (event : OrderCancelledEvent ) {
await this .readDb .query (
`UPDATE order_summaries SET status = 'cancelled', cancel_reason = $2 WHERE order_id = $1` ,
[event.orderId , event.reason ],
);
}
}
class CustomerDashboardProjection implements EventHandler {
async onOrderCreated (event : OrderCreatedEvent ) {
await this .readDb .query (
`UPDATE customer_dashboards
SET total_orders = total_orders + 1,
total_spent = total_spent + $2,
last_order_at = $3
WHERE customer_id = $1` ,
[event.customerId , event.total , event.createdAt ],
);
}
}
Event Bus Implementation
type EventSubscriber = (event : DomainEvent ) => Promise <void >;
class InMemoryEventBus implements EventBus {
private subscribers = new Map <string , EventSubscriber []>();
subscribe (eventType : string , handler : EventSubscriber ) {
const handlers = this .subscribers .get (eventType) ?? [];
handlers.push (handler);
this .subscribers .set (eventType, handlers);
}
async publish (event : DomainEvent ) {
const handlers = this .subscribers .get (event.type ) ?? [];
await Promise .allSettled (handlers.map ((h ) => h (event)));
}
}
class RabbitMQEventBus implements EventBus {
async publish (event : DomainEvent ) {
await this .channel .publish (
'domain-events' ,
event.type ,
Buffer .from (JSON .stringify (event)),
{ persistent : true , messageId : event.id },
);
}
}
Eventual Consistency Handling
async function createOrder (data : CreateOrderInput ) {
addOptimisticOrder (data);
const orderId = await commandBus.dispatch ({
type : 'CreateOrder' ,
payload : data,
});
await waitForProjection ('order_summaries' , orderId);
}
async function createOrderEndpoint (req, res ) {
const order = await commandBus.dispatch (createOrderCommand);
res.status (201 ).json ({
orderId : order.id ,
status : order.status ,
total : order.total ,
});
}
async function getOrder (req, res ) {
const minVersion = parseInt (req.headers ['if-none-match' ] ?? '0' );
const order = await queryBus.execute ({
type : 'GetOrderSummary' ,
orderId : req.params .id ,
});
if (order.version <= minVersion) {
return res.status (304 ).end ();
}
res.set ('ETag' , String (order.version ));
res.json (order);
}
Best Practices
Start simple — Separate read/write repos before adding event buses and projections.
One command, one handler — Each command has exactly one handler.
Queries are side-effect free — Read operations never modify state.
Commands return minimal data — Typically just the ID; clients query for details.
Projections must be idempotent — Events may be replayed during rebuilds.
Use persistent event storage — Required for projection rebuilds and auditing.
Handle projection lag — Clients must tolerate eventual consistency.
Separate read databases — Denormalized, optimized per query pattern.
Version projections — Allow rebuilding from events without downtime.
Monitor projection lag — Alert when read models fall behind the write model.
Common Pitfalls Pitfall Problem Fix CQRS for simple CRUD Unnecessary complexity Use CQRS only when read/write patterns diverge significantly Querying the write model Defeats the purpose of separation Read side should have its own optimized store Non-idempotent projections Replaying events corrupts read model Use upserts or track processed event IDs Synchronous projections Command latency includes projection time Project asynchronously via event bus Ignoring eventual consistency UI shows stale data Use optimistic UI, polling, or WebSocket notifications Missing correlation IDs Cannot trace command through projections Include correlationId in all commands and events