arch-cross-service-integration
Use when designing or implementing cross-service communication, data synchronization, or service boundary patterns.
Best use case
arch-cross-service-integration is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when designing or implementing cross-service communication, data synchronization, or service boundary patterns.
Teams using arch-cross-service-integration should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/arch-cross-service-integration/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How arch-cross-service-integration Compares
| Feature / Agent | arch-cross-service-integration | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when designing or implementing cross-service communication, data synchronization, or service boundary patterns.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Cross-Service Integration Workflow
## When to Use This Skill
- Designing service-to-service communication
- Implementing data synchronization
- Analyzing service boundaries
- Troubleshooting cross-service issues
## Pre-Flight Checklist
- [ ] Identify source and target services
- [ ] Determine data ownership
- [ ] Choose communication pattern (sync vs async)
- [ ] Map data transformation requirements
## Service Boundaries
### EasyPlatform Services
```
┌─────────────────────────────────────────────────────────────────────┐
│ EasyPlatform Platform │
├───────────────┬───────────────┬───────────────┬────────────────────┤
│ TextSnippet │ TextSnippet │ TextSnippet │ TextSnippet │
│ (Example) │ (Example) │ (Example) │ (Example) │
├───────────────┴───────────────┴───────────────┴────────────────────┤
│ Accounts Service │
│ (Authentication & Users) │
├─────────────────────────────────────────────────────────────────────┤
│ Shared Infrastructure │
│ RabbitMQ │ Redis │ MongoDB │ PostgreSQL │
└─────────────────────────────────────────────────────────────────────┘
```
## Communication Patterns
### Pattern 1: Entity Event Bus (Recommended)
**Use when**: Source service owns data, target services need copies.
```
Source Service Target Service
┌────────────┐ ┌────────────┐
│ Employee │──── Create ────▶ │ Repository │
│ Repository │ └────────────┘
└────────────┘ │
│ │
│ Auto-raise │
▼ ▼
┌────────────┐ ┌────────────┐
│ Producer │── RabbitMQ ────▶ │ Consumer │
└────────────┘ └────────────┘
```
**Implementation**:
```csharp
// Producer (Source: Accounts)
internal sealed class EmployeeEntityEventBusMessageProducer
: PlatformCqrsEntityEventBusMessageProducer<EmployeeEntityEventBusMessage, Employee, string>
{
public override async Task<bool> HandleWhen(PlatformCqrsEntityEvent<Employee> @event)
=> @event.EntityData.IsActive || @event.CrudAction == PlatformCqrsEntityEventCrudAction.Deleted;
}
// Consumer (Target: TextSnippet)
internal sealed class UpsertEmployeeConsumer
: PlatformApplicationMessageBusConsumer<EmployeeEntityEventBusMessage>
{
public override async Task HandleLogicAsync(EmployeeEntityEventBusMessage message, string routingKey)
{
// Wait for dependencies
// Handle Create/Update/Delete
}
}
```
### Pattern 2: Direct API Call
**Use when**: Real-time data needed, no local copy required.
```csharp
// In TextSnippet, calling Accounts API
public class AccountsApiClient
{
private readonly HttpClient _client;
public async Task<UserDto?> GetUserAsync(string userId)
{
var response = await _client.GetAsync($"/api/User/{userId}");
if (!response.IsSuccessStatusCode) return null;
return await response.Content.ReadFromJsonAsync<UserDto>();
}
}
```
**Considerations**:
- Add circuit breaker for resilience
- Cache responses when possible
- Handle service unavailability
### Pattern 3: Shared Database View (Anti-Pattern!)
**:x: DO NOT USE**: Violates service boundaries
```csharp
// WRONG - Direct cross-service database access
var accountsData = await accountsDbContext.Users.ToListAsync();
```
## Data Ownership Matrix
| Entity | Owner Service | Consumers |
|--------|---------------|-----------|
| User | Accounts | All services |
| Employee | TextSnippet | TextSnippet, TextSnippet |
| Candidate | TextSnippet | TextSnippet (on hire) |
| Company | Accounts | All services |
| Survey | TextSnippet | TextSnippet |
## Synchronization Patterns
### Full Sync (Initial/Recovery)
```csharp
// For initial data population or recovery
public class FullSyncJob : PlatformApplicationBackgroundJobExecutor
{
public override async Task ProcessAsync(object? param)
{
// Fetch all from source
var allEmployees = await sourceApi.GetAllAsync();
// Upsert to local
foreach (var batch in allEmployees.Batch(100))
{
await localRepo.CreateOrUpdateManyAsync(
batch.Select(MapToLocal),
dismissSendEvent: true);
}
}
}
```
### Incremental Sync (Event-Driven)
```csharp
// Normal operation via message bus
internal sealed class EmployeeSyncConsumer : PlatformApplicationMessageBusConsumer<EmployeeEventBusMessage>
{
public override async Task HandleLogicAsync(EmployeeEventBusMessage message, string routingKey)
{
// Check if newer than current (race condition prevention)
if (existing?.LastMessageSyncDate > message.CreatedUtcDate)
return;
// Apply change
await ApplyChange(message);
}
}
```
### Conflict Resolution
```csharp
// Use LastMessageSyncDate for ordering
entity.With(e => e.LastMessageSyncDate = message.CreatedUtcDate);
// Only update if message is newer
if (existing.LastMessageSyncDate <= message.CreatedUtcDate)
{
await repository.UpdateAsync(updatedEntity);
}
```
## Integration Checklist
### Before Integration
- [ ] Define data ownership clearly
- [ ] Document which fields sync
- [ ] Plan for missing dependencies
- [ ] Define conflict resolution strategy
### Implementation
- [ ] Message defined in PlatformExampleApp.Shared
- [ ] Producer filters appropriate events
- [ ] Consumer waits for dependencies
- [ ] Race condition handling implemented
- [ ] Soft delete handled
### Testing
- [ ] Create event flows correctly
- [ ] Update event flows correctly
- [ ] Delete event flows correctly
- [ ] Out-of-order messages handled
- [ ] Missing dependency handled
- [ ] Force sync works
## Troubleshooting
### Message Not Arriving
```bash
# Check RabbitMQ queues
rabbitmqctl list_queues
# Check producer is publishing
grep -r "HandleWhen" --include="*Producer.cs" -A 5
# Check consumer is registered
grep -r "AddConsumer" --include="*.cs"
```
### Data Mismatch
```bash
# Compare source and target counts
# In source service DB
SELECT COUNT(*) FROM Employees WHERE IsActive = 1;
# In target service DB
SELECT COUNT(*) FROM SyncedEmployees;
```
### Stuck Messages
```csharp
// Check for waiting dependencies
Logger.LogWarning("Waiting for Company {CompanyId}", companyId);
// Force reprocess
await messageBus.PublishAsync(message.With(m => m.IsForceSync = true));
```
## Anti-Patterns to AVOID
:x: **Direct database access**
```csharp
// WRONG
await otherServiceDbContext.Table.ToListAsync();
```
:x: **Synchronous cross-service calls in transaction**
```csharp
// WRONG
using var transaction = await db.BeginTransactionAsync();
await externalService.NotifyAsync(); // If fails, transaction stuck
await transaction.CommitAsync();
```
:x: **No dependency waiting**
```csharp
// WRONG - FK violation if company not synced
await repo.CreateAsync(employee); // Employee.CompanyId references Company
// CORRECT
await Util.TaskRunner.TryWaitUntilAsync(() => companyRepo.AnyAsync(...));
```
:x: **Ignoring message order**
```csharp
// WRONG - older message overwrites newer
await repo.UpdateAsync(entity);
// CORRECT - check timestamp
if (existing.LastMessageSyncDate <= message.CreatedUtcDate)
```
## Verification Checklist
- [ ] Data ownership clearly defined
- [ ] Message bus pattern used (not direct DB)
- [ ] Dependencies waited for in consumers
- [ ] Race conditions handled with timestamps
- [ ] Soft delete synchronized properly
- [ ] Force sync mechanism available
- [ ] Monitoring/alerting in place
## Task Planning Notes
- Always plan and break many small todo tasks
- Always add a final review todo task to review the works done at the end to find any fix or enhancement neededRelated Skills
backend-architecture
Design and implement scalable backend infrastructure, microservices, and system architecture patterns.
backend-architect
Expert backend architect specializing in scalable API design, microservices architecture, and distributed systems. Masters REST/GraphQL/gRPC APIs, event-driven architectures, service mesh patterns, and modern backend frameworks. Handles service boundary definition, inter-service communication, resilience patterns, and observability. Use PROACTIVELY when creating new backend services or APIs.
azure-servicebus-ts
Build messaging applications using Azure Service Bus SDK for JavaScript (@azure/service-bus). Use when implementing queues, topics/subscriptions, message sessions, dead-letter handling, or enterpri...
azure-search-documents-ts
Build search applications using Azure AI Search SDK for JavaScript (@azure/search-documents). Use when creating/managing indexes, implementing vector/hybrid search, semantic ranking, or building ag...
azure-messaging-webpubsubservice-py
Azure Web PubSub Service SDK for Python. Use for real-time messaging, WebSocket connections, and pub/sub patterns. Triggers: "azure-messaging-webpubsubservice", "WebPubSubServiceClient", "real-time",
astro-architecture
Technical architecture for Astro lead generation websites. Use when setting up new projects, configuring build tools, or establishing project foundations. For images use astro-images skill. For SEO use astro-seo skill.
assessment-architect
Generate certification exams for chapters or parts. Extracts concepts first, then generates scenario-based questions. Use "ch X" for chapter, "part X" for part.
assessing-architecture-quality
Use when assessing codebase architecture and you feel pressure to soften critique, lead with strengths, or frame problems diplomatically - provides evidence-based critical assessment resisting relationship and economic pressures
Archon Manager
Master Archon MCP for strategic project management, task tracking, and knowledge base operations. The strategic layer (WHAT/WHEN) that coordinates with Skills (HOW). Use when managing projects, tracking tasks, querying knowledge bases, or implementing the Archon+Skills two-layer architecture.
architecture
Comprehensive system architecture design and implementation workflow that orchestrates expert analysis, technical decision-making, and architectural pattern selection using the integrated toolset. Handles everything from initial system analysis to implementation-ready technical specifications.
architecture-workshop
Framework for designing new architectural mechanisms when existing patterns don't fit
architecture-validator
Validate hexagonal architecture (Domain, Application, Infrastructure, Presentation). Use when creating new files in src/, reorganizing code, or when the user requests architecture validation.