<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[D-ERYAN]]></title><description><![CDATA[D-ERYAN]]></description><link>https://dzakaeryan.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 16:12:28 GMT</lastBuildDate><atom:link href="https://dzakaeryan.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[ReLearn : System Design and Architecture - Spring Boot Implementation]]></title><description><![CDATA[In the world of software engineering, system design is the art and science of building large-scale distributed systems that are scalable, reliable, and maintainable. This guide will walk you through the essential components and considerations of syst...]]></description><link>https://dzakaeryan.dev/relearn-system-design-and-architecture-spring-boot-implementation</link><guid isPermaLink="true">https://dzakaeryan.dev/relearn-system-design-and-architecture-spring-boot-implementation</guid><category><![CDATA[Java]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Dzaka Eryan Blog]]></dc:creator><pubDate>Wed, 22 Oct 2025 03:39:34 GMT</pubDate><content:encoded><![CDATA[<p>In the world of software engineering, system design is the art and science of building large-scale distributed systems that are scalable, reliable, and maintainable. This guide will walk you through the essential components and considerations of system design with a focus on real-world implementations using Java Spring and microservices.</p>
<h2 id="heading-why-system-design-matters">Why System Design Matters</h2>
<p>Modern applications need to handle:</p>
<ul>
<li><p>Millions of concurrent users</p>
</li>
<li><p>Petabytes of data</p>
</li>
<li><p>Sub-second response times</p>
</li>
<li><p>99.99% uptime requirements</p>
</li>
<li><p>Global distribution</p>
</li>
</ul>
<p>Understanding system design principles is crucial for building systems that can meet these demanding requirements while remaining maintainable and cost-effective.</p>
<h2 id="heading-core-system-components">Core System Components</h2>
<h3 id="heading-1-load-balancer-implementation">1. Load Balancer Implementation</h3>
<p>Load balancers are crucial for distributing traffic across multiple service instances. Here’s how to implement it with Spring Cloud:</p>
<pre><code class="lang-plaintext">@Configuration
public class LoadBalancerConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Service
public class UserService {
    private final RestTemplate restTemplate;

    public UserService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public UserProfile getUserProfile(Long userId) {
        // Load balanced request to user-profile-service
        return restTemplate.getForObject(
            "http://user-profile-service/api/profiles/{id}",
            UserProfile.class,
            userId
        );
    }
}
</code></pre>
<h3 id="heading-2-api-gateway-pattern">2. API Gateway Pattern</h3>
<p>Implementing API Gateway using Spring Cloud Gateway:</p>
<pre><code class="lang-plaintext">@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user_route", r -&gt; r
                .path("/api/users/**")
                .filters(f -&gt; f
                    .rewritePath("/api/(?&lt;segment&gt;.*)", "/${segment}")
                    .addRequestHeader("X-Gateway-Source", "spring-cloud-gateway")
                    .retry(config -&gt; config.setRetries(3))
                )
                .uri("lb://user-service")
            )
            .route("order_route", r -&gt; r
                .path("/api/orders/**")
                .filters(f -&gt; f
                    .circuitBreaker(config -&gt; config
                        .setName("orderCircuitBreaker")
                        .setFallbackUri("forward:/fallback/orders"))
                )
                .uri("lb://order-service")
            )
            .build();
    }
}j
</code></pre>
<h3 id="heading-3-service-registry">3. Service Registry</h3>
<p>Implementing service discovery with Eureka:</p>
<pre><code class="lang-plaintext">@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistryApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceRegistryApplication.class, args);
    }
}

# application.yml for Eureka Server
server:
  port: 8761
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0
    enableSelfPreservation: false

# Client Service Configuration
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}
</code></pre>
<h3 id="heading-4-configuration-management">4. Configuration Management</h3>
<p>Implementing centralized configuration with Spring Cloud Config:</p>
<pre><code class="lang-plaintext">@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

# application.yml for Config Server
spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-org/config-repo
          searchPaths: '{application}'
          default-label: main
          clone-on-start: true
          force-pull: true

# Client Configuration
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "app")
public class ApplicationConfig {
    private String apiKey;
    private int maxConnections;
    private Duration timeout;

    // Getters and setters
}
</code></pre>
<h3 id="heading-5-message-queue-integration">5. Message Queue Integration</h3>
<p>Implementing async communication with Spring Cloud Stream:</p>
<pre><code class="lang-plaintext">@Configuration
public class MessageQueueConfig {
    @Bean
    public Function&lt;Message&lt;OrderEvent&gt;, Message&lt;OrderProcessedEvent&gt;&gt; processOrder() {
        return message -&gt; {
            OrderEvent order = message.getPayload();
            // Process order
            return MessageBuilder
                .withPayload(new OrderProcessedEvent(order.getId()))
                .build();
        };
    }
}
</code></pre>
<pre><code class="lang-plaintext"># application.yml
spring:
  cloud:
    stream:
      bindings:
        processOrder-in-0:
          destination: orders
          group: order-processing-group
        processOrder-out-0:
          destination: processed-orders
      kafka:
        binder:
          brokers: localhost:9092
</code></pre>
<h2 id="heading-data-management-and-storage">Data Management and Storage</h2>
<h3 id="heading-1-database-sharding-implementation">1. Database Sharding Implementation</h3>
<pre><code class="lang-plaintext">@Configuration
public class ShardingConfiguration {
    @Bean
    public DataSource shardingDataSource() {
        Map&lt;String, DataSource&gt; dataSourceMap = new HashMap&lt;&gt;();
        dataSourceMap.put("ds0", createDataSource("jdbc:mysql://shard1/db"));
        dataSourceMap.put("ds1", createDataSource("jdbc:mysql://shard2/db"));

        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(getUserTableRuleConfiguration());

        return ShardingDataSourceFactory.createDataSource(
            dataSourceMap,
            shardingRuleConfig,
            new Properties()
        );
    }

    private TableRuleConfiguration getUserTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration("user", 
            "ds${0..1}.user${0..1}");
        result.setTableShardingStrategyConfig(
            new StandardShardingStrategyConfiguration("id", 
                new UserIdShardingAlgorithm())
        );
        return result;
    }
}
</code></pre>
<h3 id="heading-2-caching-strategy-implementation">2. Caching Strategy Implementation</h3>
<pre><code class="lang-plaintext">@Configuration
@EnableCaching
public class CacheConfiguration {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(60))
            .serializeKeysWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));

        return RedisCacheManager.builder(redisConnectionFactory)
            .cacheDefaults(config)
            .withInitialCacheConfigurations(Map.of(
                "users", RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofMinutes(10)),
                "products", RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofHours(1))
            ))
            .build();
    }
}

@Service
public class ProductService {
    private final ProductRepository repository;

    @Cacheable(value = "products", key = "#id", unless = "#result == null")
    public Product getProduct(Long id) {
        return repository.findById(id)
            .orElseThrow(() -&gt; new ProductNotFoundException(id));
    }

    @CacheEvict(value = "products", key = "#id")
    public void updateProduct(Long id, ProductUpdateRequest request) {
        Product product = repository.findById(id)
            .orElseThrow(() -&gt; new ProductNotFoundException(id));
        // Update product
        repository.save(product);
    }

    @Caching(evict = {
        @CacheEvict(value = "products", key = "#id"),
        @CacheEvict(value = "product-recommendations", allEntries = true)
    })
    public void deleteProduct(Long id) {
        repository.deleteById(id);
    }
}
</code></pre>
<h3 id="heading-3-event-sourcing-pattern">3. Event Sourcing Pattern</h3>
<pre><code class="lang-plaintext">@Entity
@Table(name = "events")
public class Event {
    @Id
    @GeneratedValue
    private Long id;

    private String aggregateId;
    private String type;
    private String data;
    private LocalDateTime timestamp;
    private Long version;
}

@Service
public class OrderEventSourcingService {
    private final EventStore eventStore;
    private final ObjectMapper objectMapper;

    public Order reconstructOrderState(String orderId) {
        List&lt;Event&gt; events = eventStore.getEvents(orderId);
        Order order = new Order(orderId);

        for (Event event : events) {
            switch (event.getType()) {
                case "ORDER_CREATED":
                    OrderCreatedEvent created = parse(event, OrderCreatedEvent.class);
                    order.apply(created);
                    break;
                case "ORDER_UPDATED":
                    OrderUpdatedEvent updated = parse(event, OrderUpdatedEvent.class);
                    order.apply(updated);
                    break;
                // Handle other events
            }
        }

        return order;
    }

    public void saveEvent(String orderId, Object event) {
        Event dbEvent = new Event();
        dbEvent.setAggregateId(orderId);
        dbEvent.setType(event.getClass().getSimpleName());
        dbEvent.setData(objectMapper.writeValueAsString(event));
        dbEvent.setTimestamp(LocalDateTime.now());

        eventStore.save(dbEvent);
    }
}
</code></pre>
<h3 id="heading-4-cqrs-implementation">4. CQRS Implementation</h3>
<pre><code class="lang-plaintext">// Command Side
@Service
public class OrderCommandService {
    private final OrderRepository repository;
    private final EventPublisher eventPublisher;

    @Transactional
    public void createOrder(CreateOrderCommand command) {
        Order order = new Order(command.getCustomerId(), command.getItems());
        repository.save(order);

        eventPublisher.publish(new OrderCreatedEvent(
            order.getId(),
            order.getCustomerId(),
            order.getItems()
        ));
    }
}

// Query Side
@Service
public class OrderQueryService {
    private final OrderProjection orderProjection;

    public OrderDTO getOrder(String orderId) {
        return orderProjection.getOrder(orderId);
    }

    public List&lt;OrderDTO&gt; getCustomerOrders(String customerId) {
        return orderProjection.getOrdersByCustomer(customerId);
    }
}

// Event Handler
@Service
public class OrderEventHandler {
    private final OrderProjection orderProjection;

    @EventListener
    public void on(OrderCreatedEvent event) {
        orderProjection.handle(event);
    }

    @EventListener
    public void on(OrderUpdatedEvent event) {
        orderProjection.handle(event);
    }
}
</code></pre>
<h2 id="heading-scalability-and-performance">Scalability and Performance</h2>
<h3 id="heading-1-horizontal-scaling-implementation">1. Horizontal Scaling Implementation</h3>
<pre><code class="lang-plaintext">@Configuration
public class ScalingConfiguration {
    @Bean
    public HazelcastInstance hazelcastInstance() {
        Config config = new Config();
        config.setInstanceName("hazelcast-instance")
              .addMapConfig(
                  new MapConfig()
                      .setName("configuration-map")
                      .setEvictionConfig(
                          new EvictionConfig()
                              .setEvictionPolicy(EvictionPolicy.LRU)
                              .setMaxSizePolicy(MaxSizePolicy.PER_NODE)
                              .setSize(10000)
                      )
              );

        return Hazelcast.newHazelcastInstance(config);
    }
}

@Service
public class DistributedCacheService {
    private final HazelcastInstance hazelcastInstance;

    public void putValue(String key, Object value) {
        IMap&lt;String, Object&gt; map = hazelcastInstance.getMap("distributed-map");
        map.put(key, value);
    }

    public Optional&lt;Object&gt; getValue(String key) {
        IMap&lt;String, Object&gt; map = hazelcastInstance.getMap("distributed-map");
        return Optional.ofNullable(map.get(key));
    }
}
</code></pre>
<h3 id="heading-2-asynchronous-processing">2. Asynchronous Processing</h3>
<pre><code class="lang-plaintext">@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("AsyncThread-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

@Service
public class OrderProcessingService {
    private final NotificationService notificationService;
    private final InventoryService inventoryService;

    @Async
    public CompletableFuture&lt;OrderResult&gt; processOrder(Order order) {
        return CompletableFuture.supplyAsync(() -&gt; {
            // Process order asynchronously
            OrderResult result = new OrderResult();

            // Parallel processing using CompletableFuture
            CompletableFuture&lt;Void&gt; notification = 
                CompletableFuture.runAsync(() -&gt; 
                    notificationService.notifyCustomer(order.getCustomerId()));

            CompletableFuture&lt;InventoryResult&gt; inventory = 
                CompletableFuture.supplyAsync(() -&gt; 
                    inventoryService.updateInventory(order.getItems()));

            // Wait for all async operations to complete
            CompletableFuture.allOf(notification, inventory).join();

            result.setInventoryResult(inventory.get());
            return result;
        });
    }
}
</code></pre>
<h3 id="heading-3-rate-limiting">3. Rate Limiting</h3>
<pre><code class="lang-plaintext">@Configuration
public class RateLimitingConfig {
    @Bean
    public RateLimiter rateLimiter() {
        return RateLimiter.create(100.0); // 100 requests per second
    }
}

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    private final RateLimiter rateLimiter;
    private final OrderService orderService;

    @PostMapping
    public ResponseEntity&lt;?&gt; createOrder(@RequestBody OrderRequest request) {
        if (!rateLimiter.tryAcquire()) {
            return ResponseEntity
                .status(HttpStatus.TOO_MANY_REQUESTS)
                .body("Too many requests - please try again later");
        }

        return ResponseEntity.ok(orderService.createOrder(request));
    }
}

// Bucket4j implementation for more sophisticated rate limiting
@Service
public class RateLimitingService {
    private final LoadingCache&lt;String, Bucket&gt; cache;

    public RateLimitingService() {
        Bandwidth limit = Bandwidth.classic(20, Refill.greedy(20, Duration.ofMinutes(1)));

        this.cache = Caffeine.newBuilder()
            .expireAfterWrite(Duration.ofHours(1))
            .build(key -&gt; Bucket.builder()
                .addLimit(limit)
                .build());
    }

    public boolean tryConsume(String key) {
        return cache.get(key).tryConsume(1);
    }
}
</code></pre>
<h3 id="heading-4-performance-monitoring">4. Performance Monitoring</h3>
<pre><code class="lang-plaintext">@Configuration
public class MetricsConfig {
    @Bean
    MeterRegistry meterRegistry() {
        return new SimpleMeterRegistry();
    }
}

@Service
@Timed("service.orders")
public class OrderMetricsService {
    private final MeterRegistry meterRegistry;
    private final Counter orderCounter;
    private final Timer processTimer;

    public OrderMetricsService(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.orderCounter = meterRegistry.counter("orders.created");
        this.processTimer = meterRegistry.timer("orders.processing.time");
    }

    public void recordOrderCreation() {
        orderCounter.increment();
    }

    public void recordProcessingTime(long milliseconds) {
        processTimer.record(milliseconds, TimeUnit.MILLISECONDS);
    }

    @Scheduled(fixedRate = 60000)
    public void reportMetrics() {
        Gauge.builder("orders.backlog", orderQueue, Queue::size)
            .tag("status", "pending")
            .register(meterRegistry);
    }
}
</code></pre>
<h2 id="heading-security-and-resilience">Security and Resilience</h2>
<h3 id="heading-1-oauth2-security-implementation">1. OAuth2 Security Implementation</h3>
<pre><code class="lang-plaintext">@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .oauth2ResourceServer()
                .jwt()
            .and()
            .authorizeRequests()
                .antMatchers("/api/public/**").permitAll()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
            .csrf().disable()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withJwkSetUri("https://auth-server/.well-known/jwks.json")
            .build();
    }
}

@RestController
@RequestMapping("/api")
public class SecuredController {
    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/admin/stats")
    public AdminStats getAdminStats() {
        // Only accessible by admin users
        return adminService.getStats();
    }

    @PreAuthorize("#userId == authentication.principal.id")
    @GetMapping("/users/{userId}")
    public UserProfile getUserProfile(@PathVariable String userId) {
        // Only accessible by the user themselves
        return userService.getProfile(userId);
    }
}
</code></pre>
<h3 id="heading-2-circuit-breaker-pattern">2. Circuit Breaker Pattern</h3>
<pre><code class="lang-plaintext">@Configuration
public class ResilienceConfig {
    @Bean
    public CircuitBreakerRegistry circuitBreakerRegistry() {
        CircuitBreakerConfig config = CircuitBreakerConfig.custom()
            .failureRateThreshold(50)
            .waitDurationInOpenState(Duration.ofSeconds(60))
            .permittedNumberOfCallsInHalfOpenState(10)
            .slidingWindowSize(100)
            .build();

        return CircuitBreakerRegistry.of(config);
    }
}

@Service
public class PaymentService {
    private final CircuitBreaker circuitBreaker;
    private final PaymentGateway paymentGateway;

    public PaymentService(CircuitBreakerRegistry registry) {
        this.circuitBreaker = registry.circuitBreaker("payment-service");
    }

    public PaymentResult processPayment(PaymentRequest request) {
        return circuitBreaker.executeSupplier(() -&gt; {
            try {
                return paymentGateway.processPayment(request);
            } catch (Exception e) {
                throw new PaymentProcessingException("Payment failed", e);
            }
        });
    }

    private PaymentResult fallback(PaymentRequest request, Exception ex) {
        // Fallback logic when circuit is open
        return PaymentResult.builder()
            .status(PaymentStatus.PENDING)
            .message("Service temporarily unavailable")
            .build();
    }
}
</code></pre>
<h3 id="heading-3-retry-pattern">3. Retry Pattern</h3>
<pre><code class="lang-plaintext">@Configuration
public class RetryConfig {
    @Bean
    public RetryRegistry retryRegistry() {
        RetryConfig config = RetryConfig.custom()
            .maxAttempts(3)
            .waitDuration(Duration.ofSeconds(2))
            .retryExceptions(TimeoutException.class, IOException.class)
            .ignoreExceptions(IllegalArgumentException.class)
            .build();

        return RetryRegistry.of(config);
    }
}

@Service
public class ExternalServiceClient {
    private final Retry retry;
    private final WebClient webClient;

    public ExternalServiceClient(RetryRegistry registry) {
        this.retry = registry.retry("external-service");
    }

    public ExternalData fetchData(String id) {
        return retry.executeSupplier(() -&gt; 
            webClient.get()
                .uri("/api/data/" + id)
                .retrieve()
                .bodyToMono(ExternalData.class)
                .block()
        );
    }
}
</code></pre>
<h3 id="heading-4-distributed-tracing">4. Distributed Tracing</h3>
<pre><code class="lang-plaintext">@Configuration
public class TracingConfig {
    @Bean
    public Tracer jaegerTracer() {
        return new Configuration("my-service")
            .withSampler(new Configuration.SamplerConfiguration()
                .withType(ConstSampler.TYPE)
                .withParam(1))
            .withReporter(new Configuration.ReporterConfiguration()
                .withLogSpans(true)
                .withSender(new Configuration.SenderConfiguration()
                    .withEndpoint("http://jaeger-collector:14268/api/traces")))
            .getTracer();
    }
}

@Service
public class OrderProcessingService {
    private final Tracer tracer;

    public OrderResult processOrder(Order order) {
        Span span = tracer.buildSpan("process-order")
            .withTag("orderId", order.getId())
            .start();

        try (Scope scope = tracer.scopeManager().activate(span)) {
            // Process order
            span.setTag("status", "processing");
            OrderResult result = orderProcessor.process(order);
            span.setTag("status", "completed");
            return result;
        } catch (Exception e) {
            span.setTag("error", true);
            span.log(Map.of(
                "event", "error",
                "message", e.getMessage()
            ));
            throw e;
        } finally {
            span.finish();
        }
    }
}
</code></pre>
<p>The guide covers building scalable systems using Spring Boot and architectural principles</p>
]]></content:encoded></item><item><title><![CDATA[Hexagonal Architecture dengan Golang dan Implementasinya pada Sistem Manajemen Rumah Sakit]]></title><description><![CDATA[Pendahuluan
Dalam pengembangan perangkat lunak berskala besar seperti Sistem Informasi Manajemen Rumah Sakit (SIMRS), arsitektur aplikasi memegang peranan penting agar sistem tetap fleksibel, mudah dikembangkan, dan terukur. Salah satu pendekatan mod...]]></description><link>https://dzakaeryan.dev/hexagonal-architecture-dengan-golang-dan-implementasinya-pada-sistem-manajemen-rumah-sakit</link><guid isPermaLink="true">https://dzakaeryan.dev/hexagonal-architecture-dengan-golang-dan-implementasinya-pada-sistem-manajemen-rumah-sakit</guid><dc:creator><![CDATA[Dzaka Eryan Blog]]></dc:creator><pubDate>Tue, 02 Sep 2025 12:17:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-pendahuluan">Pendahuluan</h2>
<p>Dalam pengembangan perangkat lunak berskala besar seperti <strong>Sistem Informasi Manajemen Rumah Sakit (SIMRS)</strong>, arsitektur aplikasi memegang peranan penting agar sistem tetap <strong>fleksibel, mudah dikembangkan, dan terukur</strong>. Salah satu pendekatan modern yang banyak digunakan adalah <strong>Hexagonal Architecture</strong> (atau dikenal juga sebagai <strong>Ports and Adapters Pattern</strong>).</p>
<p>Artikel ini membahas konsep dasar Hexagonal Architecture, implementasi dengan <strong>Golang</strong>, serta studi kasus penerapannya pada modul SIMRS.</p>
<hr />
<h2 id="heading-konsep-hexagonal-architecture">Konsep Hexagonal Architecture</h2>
<p>Hexagonal Architecture pertama kali diperkenalkan oleh <strong>Alistair Cockburn</strong>. Ide utamanya adalah <strong>memisahkan inti bisnis aplikasi (domain) dari detail teknis</strong> seperti database, API, maupun UI.</p>
<p>Struktur utamanya:</p>
<ol>
<li><p><strong>Domain / Core</strong> – berisi logika bisnis inti.</p>
</li>
<li><p><strong>Ports</strong> – interface yang mendefinisikan cara domain berinteraksi dengan dunia luar.</p>
</li>
<li><p><strong>Adapters</strong> – implementasi konkret dari ports (misalnya database adapter, REST API, gRPC, message broker, dll).</p>
</li>
</ol>
<p>Dengan cara ini:</p>
<ul>
<li><p>Logika bisnis tetap murni dan tidak terikat pada framework/teknologi tertentu.</p>
</li>
<li><p>Infrastruktur (database, UI, API) dapat diganti tanpa memengaruhi domain.</p>
</li>
</ul>
<hr />
<h2 id="heading-mengapa-golang-cocok">Mengapa Golang Cocok?</h2>
<p>Golang memiliki beberapa keunggulan untuk membangun aplikasi berbasis Hexagonal Architecture:</p>
<ul>
<li><p><strong>Sederhana</strong>: Sintaks minimalis memudahkan developer memahami struktur domain.</p>
</li>
<li><p><strong>Strong typing</strong>: Cocok untuk membuat kontrak (ports) yang jelas.</p>
</li>
<li><p><strong>Performant</strong>: Efisien untuk sistem yang membutuhkan performa tinggi seperti SIMRS.</p>
</li>
<li><p><strong>Ekosistem</strong>: Dukungan library untuk REST, gRPC, SQL/NoSQL, message broker, dll.</p>
</li>
</ul>
<hr />
<h2 id="heading-struktur-project-hexagonal-di-golang">Struktur Project Hexagonal di Golang</h2>
<p>Contoh struktur sederhana:</p>
<pre><code class="lang-plaintext">/simrs
  /cmd
    /app        # main program
  /internal
    /domain     # entity dan business logic
    /ports      # interface (ports)
    /adapters   # database, api, dll
    /usecase    # application services
</code></pre>
<h3 id="heading-contoh-domain-entity-pasien">Contoh Domain (Entity Pasien)</h3>
<pre><code class="lang-plaintext">package domain

type Patient struct {
    ID       string
    Name     string
    Age      int
    Address  string
}
</code></pre>
<h3 id="heading-ports-repository-interface">Ports (Repository Interface)</h3>
<pre><code class="lang-plaintext">package ports

import "simrs/internal/domain"

type PatientRepository interface {
    Save(patient domain.Patient) error
    FindByID(id string) (domain.Patient, error)
}
</code></pre>
<h3 id="heading-adapter-implementasi-repository-dengan-database-sql">Adapter (Implementasi Repository dengan Database SQL)</h3>
<pre><code class="lang-plaintext">package adapters

import (
    "database/sql"
    "simrs/internal/domain"
    "simrs/internal/ports"
)

type PatientRepositorySQL struct {
    DB *sql.DB
}

func (r *PatientRepositorySQL) Save(p domain.Patient) error {
    _, err := r.DB.Exec("INSERT INTO patients (id, name, age, address) VALUES (?, ?, ?, ?)",
        p.ID, p.Name, p.Age, p.Address)
    return err
}

func (r *PatientRepositorySQL) FindByID(id string) (domain.Patient, error) {
    row := r.DB.QueryRow("SELECT id, name, age, address FROM patients WHERE id = ?", id)
    var p domain.Patient
    err := row.Scan(&amp;p.ID, &amp;p.Name, &amp;p.Age, &amp;p.Address)
    return p, err
}
</code></pre>
<h3 id="heading-use-case-aplikasi">Use Case (Aplikasi)</h3>
<pre><code class="lang-plaintext">package usecase

import (
    "simrs/internal/domain"
    "simrs/internal/ports"
)

type PatientService struct {
    Repo ports.PatientRepository
}

func (s *PatientService) RegisterPatient(p domain.Patient) error {
    return s.Repo.Save(p)
}
</code></pre>
<h3 id="heading-entry-point-rest-api-sebagai-adapter">Entry Point (REST API sebagai Adapter)</h3>
<pre><code class="lang-plaintext">package adapters

import (
    "encoding/json"
    "net/http"
    "simrs/internal/domain"
    "simrs/internal/usecase"
)

type PatientHandler struct {
    Service *usecase.PatientService
}

func (h *PatientHandler) Register(w http.ResponseWriter, r *http.Request) {
    var p domain.Patient
    json.NewDecoder(r.Body).Decode(&amp;p)
    err := h.Service.RegisterPatient(p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    w.WriteHeader(http.StatusCreated)
}
</code></pre>
<hr />
<h2 id="heading-studi-kasus-implementasi-pada-simrs">Studi Kasus: Implementasi pada SIMRS</h2>
<p>Pada <strong>SIMRS</strong>, modularisasi sangat penting. Contoh penerapan Hexagonal Architecture:</p>
<ul>
<li><p><strong>Modul Pasien</strong> → menangani pendaftaran pasien, rekam medis.</p>
</li>
<li><p><strong>Modul Dokter</strong> → manajemen jadwal dan data dokter.</p>
</li>
<li><p><strong>Modul Billing</strong> → integrasi keuangan, pembayaran, asuransi BPJS.</p>
</li>
<li><p><strong>Modul Apotek</strong> → manajemen obat, stok, dan distribusi.</p>
</li>
</ul>
<p>Dengan Hexagonal:</p>
<ul>
<li><p><strong>Domain</strong> setiap modul berdiri sendiri.</p>
</li>
<li><p><strong>Ports</strong> didefinisikan sebagai kontrak layanan antar modul.</p>
</li>
<li><p><strong>Adapters</strong> bisa berupa REST API, gRPC, atau event message.</p>
</li>
</ul>
<p>Misalnya: Modul <strong>Billing</strong> dapat mengganti database MySQL ke PostgreSQL tanpa mengubah domain. Modul <strong>Apotek</strong> dapat ditambahkan integrasi dengan mesin kasir tanpa memengaruhi logika inti.</p>
<hr />
<h2 id="heading-keuntungan-untuk-simrs">Keuntungan untuk SIMRS</h2>
<ul>
<li><p><strong>Maintainability</strong>: Sistem lebih mudah dikembangkan walau kompleks.</p>
</li>
<li><p><strong>Scalability</strong>: Modul bisa dikembangkan paralel oleh tim berbeda.</p>
</li>
<li><p><strong>Testability</strong>: Domain dapat diuji tanpa tergantung infrastruktur.</p>
</li>
<li><p><strong>Flexibility</strong>: Teknologi database/API dapat diganti tanpa ubah domain.</p>
</li>
</ul>
<hr />
<h2 id="heading-kesimpulan">Kesimpulan</h2>
<p>Hexagonal Architecture memberikan fondasi yang kokoh untuk membangun <strong>SIMRS</strong> yang kompleks, fleksibel, dan terukur. Dengan menggunakan <strong>Golang</strong>, developer bisa mendapatkan performa tinggi sekaligus arsitektur yang bersih dan mudah dikembangkan.</p>
<p>Pendekatan ini memungkinkan setiap modul SIMRS berkembang secara independen, mudah diintegrasikan, dan tetap menjaga konsistensi logika bisnis rumah sakit.</p>
]]></content:encoded></item><item><title><![CDATA[Mengenal LangChain]]></title><description><![CDATA[Panduan Memulai LangChain
LangChain adalah framework pengembangan aplikasi berbasis large language model (LLM) seperti GPT-3, GPT-4, Hugging Face models, dan lainnya. Tujuan utamanya adalah memudahkan pengembang membuat aplikasi yang menggabungkan mo...]]></description><link>https://dzakaeryan.dev/mengenal-langchain</link><guid isPermaLink="true">https://dzakaeryan.dev/mengenal-langchain</guid><dc:creator><![CDATA[Dzaka Eryan Blog]]></dc:creator><pubDate>Fri, 25 Jul 2025 15:51:15 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-panduan-memulai-langchain">Panduan Memulai LangChain</h2>
<p>LangChain adalah framework pengembangan aplikasi berbasis <em>large language model</em> (LLM) seperti GPT-3, GPT-4, Hugging Face models, dan lainnya. Tujuan utamanya adalah memudahkan pengembang membuat aplikasi yang menggabungkan model bahasa dengan sumber data, agen, memori, dan templating prompt.</p>
<h3 id="heading-1-komponen-utama">1. Komponen Utama</h3>
<h4 id="heading-prompt-template">Prompt Template</h4>
<p>Template prompt memungkinkan Anda mendefinisikan format input dengan variabel seperti <code>{question}</code>. Contohnya:</p>
<pre><code class="lang-bash">Question: {question}

Answer:
</code></pre>
<p>Variabel <code>{question}</code> diganti dengan pertanyaan aktual saat runtime.</p>
<h4 id="heading-llm">LLM</h4>
<p>LangChain menyediakan antarmuka standar untuk menggunakan berbagai model bahasa seperti OpenAI, Hugging Face, dan lainnya.</p>
<h4 id="heading-chains">Chains</h4>
<p>Chains adalah rangkaian langkah yang menggabungkan prompt, LLM, dan modul lainnya:</p>
<ul>
<li><p><code>LLMChain</code>: chain sederhana dengan satu prompt dan model.</p>
</li>
<li><p><code>SimpleSequentialChain</code>: menyusun beberapa chain secara berurutan.</p>
</li>
</ul>
<h4 id="heading-agents">Agents</h4>
<p>Agen dapat memicu berbagai aktivitas atau alat secara dinamis, seperti pencarian web atau kalkulasi. Model bertindak sebagai "otak" untuk memilih aksi berdasarkan konteks.</p>
<h4 id="heading-memory">Memory</h4>
<p>LangChain mendukung memori jangka pendek dan panjang untuk menjaga konteks dalam percakapan. Misalnya, menyimpan ringkasan percakapan sebelumnya.</p>
<h3 id="heading-2-cara-memulai">2. Cara Memulai</h3>
<h4 id="heading-prasyarat">Prasyarat</h4>
<ul>
<li><p>Python 3.7+</p>
</li>
<li><p>Pemahaman dasar Python</p>
</li>
<li><p>API Key dari penyedia LLM seperti OpenAI atau Hugging Face</p>
</li>
</ul>
<h4 id="heading-instalasi">Instalasi</h4>
<pre><code class="lang-bash">pip install langchain
pip install openai
</code></pre>
<h4 id="heading-contoh-sederhana">Contoh Sederhana</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> langchain <span class="hljs-keyword">import</span> PromptTemplate, LLMChain
<span class="hljs-keyword">from</span> langchain.llms <span class="hljs-keyword">import</span> OpenAI

template = <span class="hljs-string">"""Question: {question}\n\nAnswer:"""</span>
prompt = PromptTemplate(template=template, input_variables=[<span class="hljs-string">"question"</span>])
llm = OpenAI(temperature=<span class="hljs-number">0.7</span>)

chain = LLMChain(llm=llm, prompt=prompt)
result = chain.run(question=<span class="hljs-string">"Apa ibukota Indonesia?"</span>)
print(result)
</code></pre>
<h3 id="heading-3-studi-kasus-umum">3. Studi Kasus Umum</h3>
<h4 id="heading-a-semantic-search-rag">A. Semantic Search / RAG</h4>
<ul>
<li><p>Gunakan document loader untuk membaca dokumen (PDF, teks).</p>
</li>
<li><p>Buat embedding dan simpan ke vector store (misal: Pinecone, Weaviate).</p>
</li>
<li><p>Jalankan pencarian semantik dan gunakan LLM untuk menjawab berdasarkan konteks.</p>
</li>
</ul>
<h4 id="heading-b-chatbot">B. Chatbot</h4>
<ul>
<li><p>Gunakan kombinasi chain untuk menjawab pertanyaan dan menyimpan konteks.</p>
</li>
<li><p>Agen dapat mengakses alat seperti kalkulator, API, atau mesin pencari.</p>
</li>
</ul>
<h4 id="heading-c-ekstraksi-data-terstruktur">C. Ekstraksi Data Terstruktur</h4>
<ul>
<li>Gunakan output parser seperti <code>JSONOutputParser</code>, <code>PydanticOutputParser</code> untuk menstrukturkan hasil dari model.</li>
</ul>
<h3 id="heading-4-tips-praktis-dan-debugging">4. Tips Praktis dan Debugging</h3>
<ul>
<li><p>Coba jalankan kode sederhana terlebih dahulu untuk memahami alur kerja.</p>
</li>
<li><p>Tambahkan logging untuk melacak input/output pada setiap langkah.</p>
</li>
<li><p>Gunakan caching untuk menghemat biaya API dan mempercepat respon.</p>
</li>
</ul>
<h3 id="heading-kesimpulan">Kesimpulan</h3>
<p>LangChain adalah framework yang kuat dan fleksibel untuk membangun aplikasi berbasis LLM: dari chatbot interaktif hingga sistem pencarian kontekstual dan agen otomatis. Struktur modularnya memudahkan integrasi komponen sesuai kebutuhan.</p>
]]></content:encoded></item><item><title><![CDATA[Memahami Microsoft Cybersecurity Reference Architecture (MCRA): Panduan Strategis untuk Keamanan Siber Modern]]></title><description><![CDATA[Di era digital yang terus berkembang pesat, keamanan siber menjadi prioritas utama bagi organisasi dari berbagai sektor. Ancaman yang semakin kompleks, pertumbuhan adopsi cloud, serta integrasi sistem lintas platform menuntut pendekatan keamanan yang...]]></description><link>https://dzakaeryan.dev/microsoft-cybersecurity-reference-architecture-mcra-panduan-strategis-untuk-keamanan-siber-modern</link><guid isPermaLink="true">https://dzakaeryan.dev/microsoft-cybersecurity-reference-architecture-mcra-panduan-strategis-untuk-keamanan-siber-modern</guid><category><![CDATA[#software #programmer #cloud #phishing #cybersecuritytraining #networking #itsecurity #ransomware #hacked #internet #computer #data #iot #hackingtools #networksecurity #bhfyp #cloudcomputing #anonymous #databreach #ai #windows #cloudsecurity #java #developer #microsoft #cybersecuritynews #innovation #datascience #machinelearning #bugbounty]]></category><dc:creator><![CDATA[Dzaka Eryan Blog]]></dc:creator><pubDate>Wed, 30 Apr 2025 21:19:10 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746046517749/5d83856e-cc7b-48e6-98a8-175ac7f98842.png" alt class="image--center mx-auto" /></p>
<p>Di era digital yang terus berkembang pesat, keamanan siber menjadi prioritas utama bagi organisasi dari berbagai sektor. Ancaman yang semakin kompleks, pertumbuhan adopsi cloud, serta integrasi sistem lintas platform menuntut pendekatan keamanan yang tidak hanya tangguh, tetapi juga adaptif dan terstandarisasi. Untuk menjawab tantangan ini, Microsoft menghadirkan <strong>Microsoft Cybersecurity Reference Architecture (MCRA)</strong> — sebuah kerangka kerja visual dan strategis yang dirancang untuk membantu organisasi membangun postur keamanan yang kuat dan terintegrasi.</p>
<hr />
<h2 id="heading-apa-itu-mcra">Apa Itu MCRA?</h2>
<p><strong>MCRA (Microsoft Cybersecurity Reference Architecture)</strong> adalah kumpulan diagram teknis dan panduan strategis yang menjelaskan bagaimana berbagai kapabilitas keamanan Microsoft dapat diterapkan secara menyeluruh di seluruh infrastruktur teknologi modern. MCRA tidak hanya mencakup layanan Microsoft seperti Microsoft 365 dan Azure, tetapi juga menjelaskan bagaimana solusi keamanan ini dapat terintegrasi dengan <strong>aplikasi pihak ketiga</strong> seperti ServiceNow dan Salesforce, serta <strong>platform cloud lain</strong> seperti Amazon Web Services (AWS) dan Google Cloud Platform (GCP).</p>
<hr />
<h2 id="heading-komponen-komponen-utama-dalam-mcra">Komponen-Komponen Utama dalam MCRA</h2>
<p>MCRA menyajikan diagram yang mencakup berbagai aspek penting dalam keamanan siber, antara lain:</p>
<h3 id="heading-1-kapabilitas-keamanan-siber-microsoft">1. <strong>Kapabilitas Keamanan Siber Microsoft</strong></h3>
<p>Menampilkan seluruh layanan keamanan Microsoft, mulai dari identitas dan akses, perlindungan endpoint, hingga pengelolaan insiden dan respons ancaman.</p>
<h3 id="heading-2-zero-trust-dan-zero-trust-rapid-modernization-plan-ramp">2. <strong>Zero Trust dan Zero Trust Rapid Modernization Plan (RaMP)</strong></h3>
<p>MCRA mengadopsi pendekatan <strong>Zero Trust</strong>—sebuah prinsip keamanan yang mengasumsikan bahwa tidak ada entitas (baik internal maupun eksternal) yang dapat dipercaya secara default. Rencana modernisasi cepat (RaMP) membantu organisasi melakukan transisi ke arsitektur Zero Trust secara efisien.</p>
<h3 id="heading-3-akses-pengguna-berbasis-zero-trust">3. <strong>Akses Pengguna Berbasis Zero Trust</strong></h3>
<p>Diagram ini memperlihatkan bagaimana pengguna, perangkat, dan aplikasi diakses secara aman menggunakan prinsip “verifikasi eksplisit”, “akses dengan hak paling minimal”, dan “asumsikan pelanggaran”.</p>
<h3 id="heading-4-operasi-keamanan-security-operations">4. <strong>Operasi Keamanan (Security Operations)</strong></h3>
<p>Menggambarkan peran pusat operasi keamanan (SOC), deteksi ancaman, pelaporan insiden, serta otomasi respons menggunakan alat seperti Microsoft Sentinel dan Defender.</p>
<h3 id="heading-5-teknologi-operasional-ot">5. <strong>Teknologi Operasional (OT)</strong></h3>
<p>MCRA juga mencakup keamanan untuk sistem teknologi operasional yang sering digunakan di industri manufaktur, energi, dan utilitas, yang sebelumnya sering luput dari pendekatan keamanan TI konvensional.</p>
<h3 id="heading-6-kapabilitas-multicloud-dan-lintas-platform">6. <strong>Kapabilitas Multicloud dan Lintas Platform</strong></h3>
<p>Organisasi masa kini sering mengandalkan lebih dari satu penyedia cloud. MCRA memberikan panduan bagaimana mengelola keamanan secara konsisten di lingkungan hybrid dan multicloud.</p>
<h3 id="heading-7-cakupan-rantai-serangan-attack-chain-coverage">7. <strong>Cakupan Rantai Serangan (Attack Chain Coverage)</strong></h3>
<p>Diagram ini membantu organisasi memahami bagaimana setiap lapisan solusi Microsoft dapat melindungi dari berbagai tahapan serangan, mulai dari rekayasa sosial hingga pencurian data.</p>
<h3 id="heading-8-kontrol-keamanan-bawaan-di-azure">8. <strong>Kontrol Keamanan Bawaan di Azure</strong></h3>
<p>Menjelaskan berbagai fitur keamanan yang tersedia secara native di Microsoft Azure, seperti Azure Policy, Defender for Cloud, dan Azure Firewall.</p>
<h3 id="heading-9-fungsi-organisasi-keamanan">9. <strong>Fungsi Organisasi Keamanan</strong></h3>
<p>Mengilustrasikan peran tim keamanan, kebijakan, dan tata kelola yang diperlukan untuk mendukung penerapan arsitektur keamanan modern.</p>
<hr />
<h2 id="heading-mengapa-mcra-penting">Mengapa MCRA Penting?</h2>
<p>Dengan MCRA, organisasi tidak hanya mendapatkan <strong>panduan teknis</strong>, tetapi juga <strong>kerangka strategis</strong> yang dapat dijadikan referensi untuk membangun sistem keamanan menyeluruh. MCRA membantu menyelaraskan teknologi, proses, dan sumber daya manusia dalam satu visi keamanan yang konsisten.</p>
<p>Keunggulan utama MCRA antara lain:</p>
<ul>
<li><p><strong>Meningkatkan visibilitas dan kontrol</strong> terhadap semua komponen TI dan cloud</p>
</li>
<li><p><strong>Mempercepat adopsi Zero Trust</strong> dan cloud security</p>
</li>
<li><p><strong>Memastikan integrasi mulus</strong> antar berbagai platform dan aplikasi</p>
</li>
<li><p><strong>Meningkatkan kesiapan terhadap insiden</strong> dan ketahanan terhadap ancaman</p>
</li>
</ul>
<hr />
<h2 id="heading-kesimpulan">Kesimpulan</h2>
<p>Microsoft Cybersecurity Reference Architecture (MCRA) adalah fondasi penting bagi setiap organisasi yang ingin membangun strategi keamanan siber yang modern, fleksibel, dan responsif terhadap tantangan dunia digital. Dengan pendekatan holistik yang mencakup teknologi, proses, dan kebijakan, MCRA bukan hanya alat bantu visual—melainkan peta jalan strategis untuk menciptakan sistem keamanan yang kokoh dan terpercaya.</p>
]]></content:encoded></item><item><title><![CDATA[Implementing etcd Backup and Restore]]></title><description><![CDATA[etcd is a distributed key-value store commonly used as a configuration database in distributed systems. Backing up and restoring etcd data is critical for maintaining system reliability and recovering from failures. This document outlines the steps t...]]></description><link>https://dzakaeryan.dev/implementing-etcd-backup-and-restore</link><guid isPermaLink="true">https://dzakaeryan.dev/implementing-etcd-backup-and-restore</guid><dc:creator><![CDATA[Dzaka Eryan Blog]]></dc:creator><pubDate>Thu, 10 Apr 2025 08:32:06 GMT</pubDate><content:encoded><![CDATA[<p>etcd is a distributed key-value store commonly used as a configuration database in distributed systems. Backing up and restoring etcd data is critical for maintaining system reliability and recovering from failures. This document outlines the steps to implement etcd backup and restore, including best practices.</p>
<h1 id="heading-prerequisites"><strong>Prerequisites</strong></h1>
<ol>
<li><p><strong>Access to the etcd Cluster</strong>: Ensure you have administrative access to the etcd cluster.</p>
</li>
<li><p><strong>etcdctl Installed</strong>: The <code>etcdctl</code> command-line tool should be installed and configured.</p>
</li>
<li><p><strong>Appropriate Permissions</strong>: Ensure the user executing commands has sufficient permissions to interact with etcd.</p>
</li>
<li><p><strong>Backup Storage</strong>: Decide on a reliable storage location for the backups (e.g., cloud storage, network file system).</p>
</li>
<li><p><strong>Version Compatibility</strong>: Confirm that the version of <code>etcdctl</code> matches the version of the etcd cluster.</p>
</li>
</ol>
<h1 id="heading-backup-process"><strong>Backup Process</strong></h1>
<p><strong>Identify the etcd Endpoint</strong>: Determine the etcd endpoint URL(s). For a single-node etcd, this is typically <a target="_blank" href="http://127.0.0.1:2379"><code>http://127.0.0.1:2379</code></a>. For a cluster, specify multiple endpoints.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> ETCDCTL_API=3
<span class="hljs-built_in">export</span> ETCDCTL_ENDPOINTS=<span class="hljs-string">"http://&lt;etcd-host1&gt;:2379,http://&lt;etcd-host2&gt;:2379"</span>
</code></pre>
<p><strong>Create a Backup</strong>: Use the <code>etcdctl snapshot save</code> command to create a backup of the etcd data.</p>
<pre><code class="lang-bash">etcdctl snapshot save /path/to/backup.db \
  --endpoints=<span class="hljs-variable">${ETCDCTL_ENDPOINTS}</span> \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem \
  --cacert=/path/to/ca.pem
</code></pre>
<h3 id="heading-replace-pathtobackupdb-with-the-desired-backup-file-location-and-include-tls-certificates-if-applicable"><strong><em>Repla*</em></strong>ce<em> <code>/path/to/backup.db</code> </em>with the desired backup file location and include TLS certificates if applicable.*</h3>
<p><strong>Verify the Backup</strong>: Validate the integrity of the backup using</p>
<pre><code class="lang-bash">etcdctl snapshot status /path/to/backup.db
</code></pre>
<p><strong>Store the Backup Securely</strong>: Transfer the backup to a secure, redundant storage location to prevent data loss.</p>
<h1 id="heading-restore-process"><strong>Restore Process</strong></h1>
<ul>
<li><p><strong>Stop the etcd Cluster</strong>: Stop all etcd instances before performing a restore to avoid conflicts.</p>
</li>
<li><p><strong>Restore the Backup</strong>: Use the <code>etcdctl snapshot restore</code> command to restore the backup.</p>
<pre><code class="lang-bash">  etcdctl snapshot restore /path/to/backup.db \
    --name=&lt;new-node-name&gt; \
    --data-dir=/path/to/new-data-dir \
    --initial-cluster=&lt;new-cluster-info&gt; \
    --initial-cluster-token=&lt;new-token&gt; \
    --initial-advertise-peer-urls=&lt;new-peer-urls&gt;
</code></pre>
</li>
</ul>
<ul>
<li><p><strong>Restart the Cluster</strong>: Start the etcd instance(s) with the restored data.</p>
</li>
<li><p><strong>Verify the Restoration</strong>: Confirm that the cluster is operational and the restored data is accessible.</p>
<pre><code class="lang-bash">  etcdctl get &lt;key&gt; --endpoints=<span class="hljs-variable">${ETCDCTL_ENDPOINTS}</span>
</code></pre>
</li>
</ul>
<h1 id="heading-best-practices"><strong>Best Practices</strong></h1>
<ol>
<li><p><strong>Automate Backups</strong>: Schedule regular backups using cron jobs or orchestration tools.</p>
</li>
<li><p><strong>Monitor Backup Integrity</strong>: Periodically validate backups to ensure they are usable.</p>
</li>
<li><p><strong>Secure Backup Storage</strong>: Use encryption and access controls to secure backups.</p>
</li>
<li><p><strong>Test Restores</strong>: Regularly practice restoring backups in a non-production environment to verify your process.</p>
</li>
<li><p><strong>Document the Process</strong>: Maintain clear documentation for backup and restore procedures to ensure quick recovery in case of failure.</p>
</li>
</ol>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>Implementing a robust etcd backup and restore strategy is essential for safeguarding your distributed systems. By following the steps and best practices outlined in this document, you can minimize downtime and data loss during unforeseen incidents.</p>
]]></content:encoded></item></channel></rss>