MoreRSS

site iconThe Practical DeveloperModify

A constructive and inclusive social network for software developers.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of The Practical Developer

Resolving Missing Log Gaps in Data Guard

2025-09-13 19:42:58

Fixing a standby gap has been possible since Oracle 10g using incremental backup, but it had to be done completely manually. This process required determining the SCN number, taking an incremental backup from the primary database, transferring the backup files to the standby server, and so on.
Starting from Oracle 12cR1, some improvements were introduced, and part of this process became automated. However, it still required going through several manual steps:

SQL>startup force mount

RMAN> RECOVER DATABASE FROM SERVICE prim NOREDO ;

RMAN> RESTORE STANDBY CONTROLFILE FROM SERVICE prim;

SQL>startup force;

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE;

In Oracle 18c, further improvements were made. Now, with just one command, all the above steps are performed automatically:

RMAN> RECOVER STANDBY DATABASE FROM SERVICE tns_fal_server;

Below, we will simulate this scenario.

Step 1: Checking the current status of standby vs. primary
On primary (prim):

SQL> select max(sequence#),thread# from v$archived_log group by thread#;

MAX(SEQUENCE#)    THREAD#

————– ———-

           128          1

On standby (stb):

SQL> select max(sequence#),thread#,applied from gv$archived_log group by thread#,applied order by thread#;

MAX(SEQUENCE#)    THREAD# APPLIED

————– ———- ———

           128          1 YES

As shown, the standby is in sync with the primary.

Step 2: Simulating a gap
We shut down the standby:

SQL> shutdown abort

ORACLE instance shut down.

Then, on the primary, we generate and immediately delete an archived log:

alter system switch logfile;
alter system switch logfile;

[oracle@hkm6 ~]$ rm -rf /18c/arch/1_129_972120046.dbf

When the standby is started again, it will wait for archive log 129, which was deleted:

SQL> startup

Database opened.

SQL> alter database recover managed standby database;

PR00 (PID:23943): Media Recovery Waiting for T-1.S-129

PR00 (PID:23943): Fetching gap from T-1.S-129 to T-1.S-129

At this stage, the standby is intentionally placed in a gap situation.

Step 3: Resolving the gap with Oracle 18c

  1. Cancel managed recovery on standby:
SQL>  alter database recover managed standby database cancel;

Database altered.

2. Run the new Oracle 18c command in RMAN:

RMAN> recover standby database from service prim;

Starting recover at 26-APR-18

using target database control file instead of recovery catalog

Oracle instance started

Total System Global Area    4982831184 bytes

Fixed Size                     8906832 bytes

Variable Size               1174405120 bytes

Database Buffers            3791650816 bytes

Redo Buffers                   7868416 bytes

contents of Memory Script:

{

   restore standby controlfile from service  ‘prim’;

   alter database mount standby database;

}

executing Memory Script

Starting restore at 26-APR-18

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=743 device type=DISK

channel ORA_DISK_1: starting datafile backup set restore

channel ORA_DISK_1: using network backup set from service prim

channel ORA_DISK_1: restoring control file

channel ORA_DISK_1: restore complete, elapsed time: 00:00:01

output file name=/18c/base/oradata/USEFDB18/controlfile/control01.ctl

Finished restore at 26-APR-18

released channel: ORA_DISK_1

Statement processed

contents of Memory Script:

{

  recover database from service  ‘prim’;

}

executing Memory Script

Starting recover at 26-APR-18

Starting implicit crosscheck backup at 26-APR-18

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=743 device type=DISK

Crosschecked 12 objects

Finished implicit crosscheck backup at 26-APR-18

Starting implicit crosscheck copy at 26-APR-18

using channel ORA_DISK_1

Crosschecked 2 objects

Finished implicit crosscheck copy at 26-APR-18

searching for all files in the recovery area

cataloging files…

no files cataloged

using channel ORA_DISK_1

skipping datafile 5; already restored to SCN 1506388

skipping datafile 6; already restored to SCN 1506388

skipping datafile 8; already restored to SCN 1506388

skipping datafile 57; already restored to SCN 6799373

skipping datafile 58; already restored to SCN 6799373

skipping datafile 59; already restored to SCN 6799373

channel ORA_DISK_1: starting incremental datafile backup set restore

channel ORA_DISK_1: using network backup set from service prim

destination for restore of datafile 00001: /18c/base/oradata/USEFDB18/datafile/o1_mf_system_fcvjfc9s_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:15

channel ORA_DISK_1: starting incremental datafile backup set restore

channel ORA_DISK_1: using network backup set from service prim

destination for restore of datafile 00003: /18c/base/oradata/USEFDB18/datafile/o1_mf_sysaux_fcvjh2k2_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:16

channel ORA_DISK_1: starting incremental datafile backup set restore

channel ORA_DISK_1: using network backup set from service prim

destination for restore of datafile 00004: /18c/base/oradata/USEFDB18/datafile/o1_mf_undotbs1_fcvjhvp9_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:01

channel ORA_DISK_1: starting incremental datafile backup set restore

channel ORA_DISK_1: using network backup set from service prim

destination for restore of datafile 00007: /18c/base/oradata/USEFDB18/datafile/o1_mf_users_fcvjhwty_.dbf

channel ORA_DISK_1: restore complete, elapsed time: 00:00:01

starting media recovery

media recovery complete, elapsed time: 00:00:00

Finished recover at 26-APR-18

Finished recover at 26-APR-18

RMAN>

3. Restart managed recovery:

SQL>  alter database recover managed standby database;

PR00 (PID:25374): Media Recovery Waiting for T-1.S-131 (in transit)

Step 4: Verifying the result
Now, the standby has applied archive log 130, proving the gap is resolved:

SQL> select max(sequence#),thread#,applied from gv$archived_log where RESETLOGS_ID=972120046 group by thread#,applied order by thread#;

MAX(SEQUENCE#)    THREAD# APPLIED

————– ———- ———

           130          1 YES

Adding a "Last Used" Badge to Your Website Login Page

2025-09-13 19:37:45

Your users may get confused the next time they want to log in to your website due to multiple authentication methods. Adding a “Last Used” badge - as popularly seen on websites like lovable.dev, can fix this UX problem.

While offering multiple authentication methods is beneficial, users often face a common challenge: "What did I sign up with—Google or email?" This goes beyond user preference; it's a valid user experience (UX) concern.

This small friction can lead to failed login attempts, repeated password resets, and users abandoning your software altogether.

Adding a simple helper badge like "Last Used" or "Last Login" can solve this issue once and for all. In this post, I'll show you how to implement it. Although I'll use Next.js to demonstrate, the same logic applies to any frontend framework.

Here's what we'll do:

  • 1. - Store the user’s preferred authentication method in LocalStorage.
  • 2. - Create a “Last Used” Badge component.
  • 3. - Add the component to the login page.

Disclaimer: I assume you're familiar with frontend development and have a project set up, so I won’t cover basics like starting a React.js project or handling states. I'll focus on the simple approach to adding the "Last Used" Badge, and you can complete the remaining logic yourself.

Let's start!

Step 1: Setting Up the Login Component

First, create a basic login component with multiple authentication options. The email and password fields aren't displayed initially—instead, a button acts as a placeholder. When clicked, it hides other methods and shows the email/password form.

It's also best practice to create reusable buttons for each authentication flow, e.g., . The badge component will be absolutely positioned for each method to improve UX.

'use client';

import { useState, useEffect } from 'react';

export const LAST_USED_KEY = '_app_last_login_method';

export default function LoginPage() {
  const [lastUsedMethod, setLastUsedMethod] = useState(null);
  const [showEmailFields, setShowEmailFields] = useState(false);

  // Load last used method on component mount
  useEffect(() => {
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(LAST_USED_KEY);
      setLastUsedMethod(stored);
    }
  }, []);

  // When email button is clicked, show the form fields and hide other auth methods
  const handleEmailLogin = () => {
    setShowEmailFields(true);
  };

  if (showEmailFields) {
    return (
      // Email fields component (implement your form here)
      <div className="max-w-md mx-auto p-6 bg-white rounded-lg shadow-md">
        <h2 className="text-2xl font-bold mb-6 text-center">Sign In with Email</h2>
        {/* Add your email/password form fields, submit button, etc. */}
      </div>
    );
  }

  return (
    <div className="max-w-md mx-auto p-6 bg-white rounded-lg shadow-md">
      <h2 className="text-2xl font-bold mb-6 text-center">Sign In</h2>

      {/* Email/Password Login */}
      <div className="relative mb-4">
        <button 
          className="w-full p-3 border border-gray-300 rounded-lg hover:bg-gray-50"
          onClick={handleEmailLogin}
        >
          Continue with Email
        </button>
        {lastUsedMethod === 'EMAIL' && <LastUsedBadge />}
      </div>

      <div className="text-center text-gray-400 text-sm mb-4">OR</div>

      {/* Google OAuth */}
      <div className="relative">
        <button 
          className="w-full p-3 border border-gray-300 rounded-lg hover:bg-gray-50 flex items-center justify-center"
          onClick={() => handleGoogleLogin()} // Define handleGoogleLogin below
        >
          <GoogleIcon className="w-5 h-5 mr-2" /> {/* Assume GoogleIcon is imported */}
          Continue with Google
        </button>
        {lastUsedMethod === 'GOOGLE' && <LastUsedBadge />}
      </div>
    </div>
  );
}

Now, let’s create the badge component.

Step 2: Creating the "Last Used" Badge Component

The badge provides visual feedback about the user's last used method:

const LastUsedBadge = () => {
  return (
    <div className="absolute -top-2 -right-2 z-10">
      <span className="inline-flex items-center px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full border border-blue-200">
        Last used
      </span>
    </div>
  );
};

The design is up to you. You can use a Badge component from libraries like Shadcn UI if preferred.

Step 3: Tracking Authentication Methods

Implement logic to save and retrieve the user's preferred method. Use a utility function to store it:

// Utility function to save login method
const saveLoginMethod = (method) => {
  if (typeof window !== 'undefined') {
    localStorage.setItem(LAST_USED_KEY, method);
  }
};

// Email/Password authentication handler (add to your form submit logic)
const handleEmailSubmit = async (formData) => {
  try {
    // Your authentication logic here
    const response = await signInWithEmail(formData);

    if (response.success) {
      // Save method on successful login
      saveLoginMethod('EMAIL');

      // Redirect to dashboard
      router.push('/dashboard');
    }
  } catch (error) {
    console.error('Email login failed:', error);
  }
};

// Google OAuth handler
const handleGoogleLogin = async () => {
  try {
    // Initiate OAuth flow
    const response = await signInWithGoogle();

    if (response.success) {
      // Save method on success
      saveLoginMethod('GOOGLE');

      // OAuth will handle redirect
    }
  } catch (error) {
    console.error('Google login failed:', error);
  }
};

If your app is highly security-sensitive, consider storing this in an httpOnly cookie via server actions or API routes instead of LocalStorage. I'm not aware of major security concerns with storing just the method type, but always evaluate based on your needs.

Step 4: Handling OAuth Redirect Flows

OAuth involves redirects, which can complicate tracking. Here's how to handle it.

For client-side OAuth:

// For providers that allow client-side completion
const handleGoogleLogin = async () => {
  // Save preference before initiating OAuth
  saveLoginMethod('GOOGLE');

  // Initiate OAuth flow
  window.location.href = '/auth/google';
};

For server-side callbacks with client notification (in Next.js):

// In your OAuth callback handler (/api/auth/callback/google.js)
export default async function handler(req, res) {
  try {
    // Handle OAuth callback logic
    const { user, session } = await processOAuthCallback(req);

    if (user) {
      // Redirect with login method parameter
      res.redirect('/dashboard?login_method=GOOGLE');
    }
  } catch (error) {
    res.redirect('/login?error=oauth_failed');
  }
}

Then, process the parameter on the client:

// Hook to process login method from URL params
const useLoginMethodTracker = () => {
  const router = useRouter();

  useEffect(() => {
    const urlParams = new URLSearchParams(window.location.search);
    const loginMethod = urlParams.get('login_method');

    if (loginMethod) {
      saveLoginMethod(loginMethod);

      // Clean up URL
      const url = new URL(window.location);
      url.searchParams.delete('login_method');
      window.history.replaceState({}, '', url);
    }
  }, []);
};

// Use in your dashboard or protected pages
export default function Dashboard() {
  useLoginMethodTracker();

  return <div>Welcome to your dashboard!</div>;
};

Now, try to log out and log in to your website, log out again, and try to log in, you should see something like this:

Adding

That's all, and you're done!

Website "Last Used" Best Practices and Considerations

Security

  • Store only the authentication method, not sensitive data.
  • Use sessionStorage for more sensitive apps.
  • Implement CSRF protection for all methods.

Privacy

  • Clearly inform users about locally stored data.
  • Allow users to clear this preference.

Accessibility
Ensure badges don't interfere with screen readers.
Provide ARIA labels.
Test with keyboard navigation.

Conclusion

Adding a "Last Used" badge to your login page is a small enhancement with significant UX benefits. By reducing friction and providing visual cues, you create a more intuitive experience that boosts user engagement and retention.

The implementation is straightforward, requiring minimal code changes for maximum impact. As authentication evolves, these thoughtful touches will become essential.

Do you have any questions?

From Zero to Professional: Building Unlimited Cloud Storage + Website Hosting with AWS S3

2025-09-13 19:35:00

A complete implementation guide showing how to create scalable storage, automated lifecycle management, and professional website hosting - all in one solution

🌐 See It In Action: Live Demo

🔗 Live Website: http://s3-casestudy-harry-v26.s3-website.ap-south-1.amazonaws.com/

📝 Important Note: This is the actual website deployed as part of this case study. If the link doesn't work with HTTPS, please change the URL to HTTP, as S3 static website hosting uses HTTP by default (unless CloudFront CDN is configured for HTTPS support).

This live demo showcases everything we'll build in this guide - unlimited storage, automated lifecycle management, and professional website hosting, all working together seamlessly.

The Challenge: Storage That Scales Without Breaking the Bank

Imagine you're managing XYZ Corporation's digital assets. Files keep growing, storage costs are climbing, and you need a professional website presence. Traditional solutions require expensive hardware, complex backup systems, and separate hosting services.

What if I told you there's a way to solve all these problems with a single AWS service that costs pennies and scales infinitely?

The Game-Changer: AWS S3 Multi-Feature Solution

Here's what we built in just 2.5 hours:

Unlimited cloud storage with 99.999999999% durability

Automated cost optimization saving 60% through intelligent lifecycle policies

Professional website hosting with custom domain integration

Zero data loss protection with built-in versioning

Custom error handling for seamless user experience

The best part? Monthly cost: $15-30 for what would traditionally require thousands in infrastructure investment.

Architecture That Actually Works

S3 Multi-Feature Architecture

This isn't just storage—it's a complete digital infrastructure solution:

Core Components:

  • S3 Buckets: Primary storage with intelligent tiering
  • Route 53: Custom domain DNS management
  • CloudWatch: Real-time monitoring and alerting
  • Lifecycle Policies: Automated cost optimization
  • Website Hosting: Static site deployment

Implementation Deep Dive: The Step-by-Step Journey

Challenge #1: Unlimited Storage with Smart Cost Management

The Problem: Traditional storage gets expensive fast, and you pay for capacity whether you use it or not.

The Solution: S3 with intelligent lifecycle policies.

# Create the storage bucket
aws s3 mb s3://xyz-corp-storage-unique-suffix --region us-east-1

# Configure lifecycle policy for automatic cost optimization
aws s3api put-bucket-lifecycle-configuration \
  --bucket xyz-corp-storage-unique-suffix \
  --lifecycle-configuration file://lifecycle-policy.json

Lifecycle Policy Magic:

  • Day 0-30: S3 Standard (immediate access)
  • Day 30-60: Standard-IA (20% cost reduction)
  • Day 60-75: Glacier (68% cost reduction)
  • Day 75+: Automatic deletion

Result: 60% storage cost reduction while maintaining accessibility.

Challenge #2: Data Protection Without Complexity

The Problem: Accidental deletions and data corruption happen. Traditional backup systems are complex and expensive.

The Solution: S3 Versioning with point-in-time recovery.

# Enable versioning for bulletproof data protection
aws s3api put-bucket-versioning \
  --bucket xyz-corp-storage-unique-suffix \
  --versioning-configuration Status=Enabled

What This Gives You:

  • Every file modification creates a new version
  • Instant rollback to any previous version
  • Protection against accidental deletion
  • No additional configuration required

Real-World Impact: When someone accidentally deleted critical files, we recovered everything in under 2 minutes.

Challenge #3: Professional Website Hosting

The Problem: Separate hosting services add complexity and cost.

The Solution: S3 static website hosting with custom domain.

# Configure bucket for website hosting
aws s3 website s3://your-domain-bucket \
  --index-document index.html \
  --error-document error.html

Professional Features Implemented:

  • Custom domain with Route 53 DNS
  • Professional branded 404 error pages
  • Global CDN-ready architecture
  • SSL/TLS support ready

🎯 Live Example: You can see these features in action at our live demo website - try navigating to a non-existent page to see our custom 404 error handling!

The Results: Numbers That Matter

Performance Metrics

Metric Traditional Solution AWS S3 Solution
Storage Capacity Limited by hardware Unlimited
Global Availability Single location 99.9% worldwide
Recovery Time Hours/Days Instant
Setup Time Weeks 2.5 hours
Website Response Varies <50ms globally

Cost Analysis Breakdown

Monthly Costs (Typical Usage):
├── Storage (100GB): $2.30
├── Data Transfer: $9.00  
├── Requests: $0.40
├── Route 53 DNS: $0.50
└── Total: ~$12.20/month

Traditional Alternative: $500-2000+/month

Annual Savings: $5,856 - $23,856 compared to traditional infrastructure!

Advanced Implementation Insights

Smart Public Access Strategy

Instead of making everything public (security risk), we implemented granular access control:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::xyz-corp-storage/*"
        }
    ]
}

Security Benefits:

  • Public read access for sharing
  • No public write access (prevents abuse)
  • Server-side encryption by default
  • Access logging for audit trails

Lifecycle Management That Actually Saves Money

Most implementations just delete old files. We built intelligence:

Tier 1 (0-30 days): Frequently accessed files stay in Standard
Tier 2 (30-60 days): Move to Standard-IA (same speed, lower cost)

Tier 3 (60-75 days): Archive to Glacier (long-term retention)
Tier 4 (75+ days): Automatic cleanup

Smart Feature: Multipart upload cleanup after 7 days prevents cost bloat from failed uploads.

Website Hosting with Zero Downtime

Traditional hosting requires server management. Our S3 solution provides:

  • Automatic scaling: Handle traffic spikes without configuration
  • Global distribution: Content served from nearest location
  • Maintenance-free: No servers to patch or maintain
  • Version control: Website files have complete change history

Professional Error Handling

Instead of ugly default error pages, we implemented branded 404 handling:

Custom Error Page Features:

  • Professional company branding
  • Clear navigation back to main site
  • Search functionality for lost content
  • Contact information for support

This small touch significantly improves user experience and professional credibility.

🔍 Test It Yourself: Visit http://s3-casestudy-harry-v26.s3-website.ap-south-1.amazonaws.com/nonexistent-page to see our custom 404 error page in action!

Lessons Learned: What Worked and What Didn't

What Exceeded Expectations

1. Version Control Power: Saved us multiple times from accidental deletions and modifications.

2. Cost Optimization: Lifecycle policies delivered even better savings than projected (60% vs. expected 40%).

3. Global Performance: Website loads faster than traditional hosting from any location.

4. Maintenance-Free Operation: Zero server administration overhead.

What Required Fine-Tuning

1. DNS Propagation: Route 53 setup needed 24-48 hours for global propagation.

2. Cache Headers: Had to configure proper caching for website performance.

3. Monitoring Setup: CloudWatch alarms needed custom configuration for meaningful alerts.

4. Security Testing: Bucket policies required thorough testing to prevent access issues.

Implementation Guide for Your Project

Phase 1: Foundation Setup (Week 1)

Storage Bucket Creation:

# Create primary storage bucket
aws s3 mb s3://your-corp-storage-$(date +%s) --region us-east-1

# Enable versioning immediately
aws s3api put-bucket-versioning \
  --bucket your-bucket-name \
  --versioning-configuration Status=Enabled

# Configure server-side encryption
aws s3api put-bucket-encryption \
  --bucket your-bucket-name \
  --server-side-encryption-configuration \
  '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'

Phase 2: Lifecycle Optimization (Week 1)

Automated Cost Management:

{
  "Rules": [
    {
      "ID": "CostOptimizationRule",
      "Status": "Enabled",
      "Filter": {"Prefix": ""},
      "Transitions": [
        {
          "Days": 30,
          "StorageClass": "STANDARD_IA"
        },
        {
          "Days": 60,
          "StorageClass": "GLACIER"
        }
      ],
      "Expiration": {
        "Days": 75
      }
    }
  ]
}

Phase 3: Website Deployment (Week 2)

Static Website Setup:

# Configure website hosting
aws s3 website s3://your-domain-bucket \
  --index-document index.html \
  --error-document error.html

# Upload website files
aws s3 sync ./website-files/ s3://your-domain-bucket/ \
  --acl public-read \
  --cache-control max-age=3600

Phase 4: DNS and Domain (Week 2)

Route 53 Configuration:

# Create hosted zone
aws route53 create-hosted-zone \
  --name yourdomain.com \
  --caller-reference $(date +%s)

# Add A record pointing to S3 website endpoint
aws route53 change-resource-record-sets \
  --hosted-zone-id YOUR_ZONE_ID \
  --change-batch file://dns-config.json

Advanced Features You Can Add

1. CDN Integration

Add CloudFront for global content delivery and HTTPS support:

aws cloudfront create-distribution \
  --distribution-config file://cdn-config.json

2. Advanced Monitoring

Set up comprehensive monitoring with custom metrics:

aws logs create-log-group --log-group-name /aws/s3/access-logs
aws cloudwatch put-metric-alarm \
  --alarm-name "S3-High-Requests" \
  --alarm-description "Monitor S3 request volume"

3. Cross-Region Replication

Add disaster recovery with automatic replication:

{
  "Role": "arn:aws:iam::ACCOUNT:role/replication-role",
  "Rules": [
    {
      "Status": "Enabled",
      "Priority": 1,
      "Filter": {"Prefix": ""},
      "Destination": {
        "Bucket": "arn:aws:s3:::backup-bucket-region2"
      }
    }
  ]
}

Cost Optimization Strategies That Work

1. Intelligent Tiering

Let AWS automatically optimize storage classes based on access patterns:

aws s3api put-bucket-intelligent-tiering-configuration \
  --bucket your-bucket \
  --id OptimizeStorageClass \
  --intelligent-tiering-configuration file://tiering-config.json

2. Request Optimization

Reduce API request costs with these practices:

  • Use S3 batch operations for bulk tasks
  • Implement proper caching headers
  • Optimize multipart upload thresholds
  • Use S3 Transfer Acceleration for global uploads

3. Monitoring and Alerting

Set up cost alerts to prevent surprises:

aws budgets create-budget \
  --account-id YOUR_ACCOUNT_ID \
  --budget file://s3-budget.json

Security Best Practices We Implemented

1. Encryption at Rest and Transit

  • Server-side encryption enabled by default
  • HTTPS-only access via bucket policies
  • KMS integration for sensitive data

2. Access Control

  • Principle of least privilege
  • Separate buckets for different access levels
  • Regular access audit and cleanup

3. Logging and Monitoring

  • S3 access logging enabled
  • CloudTrail for API call tracking
  • Automated security scanning

The Business Impact Beyond Technical Success

Operational Transformation

  • IT Team Productivity: 90% reduction in storage management time
  • Developer Velocity: Instant file sharing and collaboration
  • Business Continuity: Automatic backup and disaster recovery

Competitive Advantages

  • Global Reach: Serve content worldwide with consistent performance
  • Scalability: Handle traffic spikes without infrastructure changes
  • Professional Presence: Custom domain website builds brand credibility

Strategic Benefits

  • Innovation Platform: Foundation for future digital initiatives
  • Cost Predictability: Pay-as-you-grow model aligns with business growth
  • Technology Leadership: Modern infrastructure attracts top talent

What's Next: Scaling This Success

This S3 foundation enables exciting possibilities:

Immediate Enhancements

  • Content Delivery Network: CloudFront integration for global performance
  • Advanced Analytics: S3 analytics and insights for usage optimization
  • Mobile Integration: Direct mobile app integration with pre-signed URLs

Future Opportunities

  • Machine Learning: S3 data as input for ML/AI initiatives
  • Data Lake Architecture: Foundation for big data and analytics
  • Microservices Storage: Backend storage for modern applications

Key Takeaways for Your Implementation

Technical Decisions That Matter

  1. Enable versioning from day one - saves countless hours later
  2. Configure lifecycle policies early - cost optimization compounds over time
  3. Plan DNS changes in advance - propagation takes 24-48 hours
  4. Monitor everything - visibility prevents surprises

Business Considerations

  1. Start simple, scale smart - basic implementation first, optimize later
  2. Document everything - knowledge sharing accelerates team adoption
  3. Plan for growth - S3 scales, but your processes need to scale too
  4. Measure success - track both technical metrics and business impact

Avoiding Common Pitfalls

  1. Don't skip encryption - enable it from the beginning
  2. Test bucket policies thoroughly - access issues are hard to debug
  3. Monitor costs closely - especially during initial data uploads
  4. Plan backup strategies - even with 99.999999999% durability

Ready to Build Your Own S3 Solution?

This implementation proves that professional, scalable cloud infrastructure doesn't require enterprise budgets or dedicated DevOps teams. With the right approach, you can build world-class storage and hosting solutions in hours, not months.

Want to see the complete implementation? Check out my GitHub repository with all configurations, scripts, and step-by-step documentation.

The repository includes:
📂 Complete automation scripts for one-click deployment

🔧 Configuration templates for common use cases

📊 Cost calculation spreadsheets for budget planning

🧪 Testing procedures for validation and troubleshooting

📚 Best practices guide based on real-world experience

🌐 Live Demo: Don't forget to check out the actual working website to see all these features in action!

This case study was completed as part of my Executive Post Graduate Certification in Cloud Computing at iHub Divyasampark, IIT Roorkee. The implementation demonstrates enterprise-grade cloud architecture principles applied to real-world business requirements.

Ready to transform your storage and hosting strategy?

📧 [email protected]

💼 Connect on LinkedIn

💻 View All Projects

📝 Follow My Blog

What's your biggest storage challenge? Drop a comment below and let's solve it together using AWS S3's powerful capabilities!

Tags: #AWS #S3 #CloudStorage #WebsiteHosting #CostOptimization #LifecycleManagement #CloudComputing #DevOps #InfrastructureAsCode #IITRoorkee

Service Discovery: The Backbone of Modern Distributed Systems day 50 of system design

2025-09-13 19:31:15

Back when applications ran on a single server, life was simple. Today’s modern applications are far more complex, consisting of dozens or even hundreds of services, each with multiple instances that scale up and down dynamically. This complexity makes it challenging for services to efficiently find and communicate with each other across networks. That’s where Service Discovery comes into play.

In this article, we’ll explore what service discovery is, why it’s critical, how it works, the different types (client-side and server-side discovery), and best practices for implementing it effectively.

What is Service Discovery?

Service discovery is a mechanism that enables services in a distributed system to dynamically find and communicate with each other. It abstracts the complexity of service locations, allowing services to interact without needing to know each other’s exact network addresses.

At its core, service discovery relies on a service registry, a centralized database that acts as a single source of truth for all services. This registry stores essential information about each service, enabling seamless querying and communication.

What Does a Service Registry Store?

A typical service registry record includes:

  • Basic Details: Service name, IP address, port, and status.

  • Metadata: Version, environment, region, tags, etc.

  • Health Information: Health status and last health check.

  • Load Balancing Info: Weights and priorities.

  • Secure Communication: Protocols and certificates.

Why is Service Discovery Important?

Imagine a massive system like Netflix, with hundreds of microservices working together. Hardcoding service locations isn’t feasible—when a service moves or scales, it could break the entire system. Service discovery addresses this by enabling dynamic and reliable service location and communication.

Key Benefits of Service Discovery

  • Reduced Manual Configuration: Services automatically discover and connect, eliminating the need for hardcoding network locations.

  • Improved Scalability: Service discovery adapts to changing environments as services scale up or down.

  • Fault Tolerance: Integrated health checks allow systems to reroute traffic away from failing instances.

  • Simplified Management: A central registry simplifies monitoring, management, and troubleshooting.

Service Registration Options

Service registration is the process by which a service announces its availability to the service registry, making it discoverable. The method of registration depends on the architecture, tools, and deployment environment. Here are the most common approaches:

  1. Manual Registration

In manual registration, developers or operators manually add service details to the registry. While simple, this approach is impractical for dynamic systems where services frequently scale or move.

  1. Self-Registration

In self-registration, services register themselves with the registry upon startup. The service includes logic to send its network details (e.g., IP address and port) to the registry via API calls (e.g., HTTP or gRPC). Services may also send periodic heartbeat signals to confirm their health and availability.

  1. Third-Party Registration (Sidecar Pattern)

In third-party registration, an external agent or "sidecar" process handles registration. The sidecar runs alongside the service (e.g., in the same container) and registers the service’s details with the registry on its behalf.

  1. Automatic Registration by Orchestrators

In orchestrated environments like Kubernetes, service registration is automatic. The orchestrator manages the service lifecycle, assigning IP addresses and ports and updating the registry as services start, stop, or scale. For example, Kubernetes uses its built-in DNS for service discovery.

  1. Configuration Management Systems

Tools like Chef, Puppet, or Ansible can manage service lifecycles and update the registry when services are added or removed

Types of Service Discovery

Service discovery can be broadly categorized into two models: client-side discovery and server-side discovery.

Client-Side Discovery

In client-side discovery, the client (e.g., a microservice or API gateway) is responsible for querying the service registry and routing requests to the appropriate service instance.

How It Works

  • Service Registration: Services (e.g., UserService, PaymentService) register their network details (IP address, port) and metadata with the service registry.

  • Client Queries the Registry: The client queries the registry to retrieve a list of available instances for a target service.

  • Client Routes the Request: The client selects an instance (e.g., using a load balancing algorithm) and connects directly to it.

xample Workflow

Consider a food delivery app:

  • The PaymentService has three instances running on different servers.

  • The OrderService queries the registry for PaymentService instances.

  • The registry returns a list of instances (e.g., IP1:Port1, IP2:Port2, IP3:Port3).

  • The OrderService selects an instance (e.g., IP1:Port1) and sends the payment request.

Advantages

  • Simple to implement and understand.

  • Reduces load on central infrastructure

Disadvantages

  • Clients must implement discovery logic.

  • Changes in the registry protocol require client updates.

Example Workflow

For an e-commerce platform:

  • The PaymentService registers two instances: IP1:8080 and IP2:8081.

  • The OrderService sends a request to the load balancer, specifying PaymentService.

  • The load balancer queries the registry, selects an instance (e.g., IP1:8080), and routes the request.

  • The PaymentService processes the request and responds via the load balancer.

Advantages

  • Centralizes discovery logic, reducing client complexity.

  • Easier to manage and update discovery protocols.

Disadvantages

  • Introduces an additional network hop.

  • The load balancer can become a single point of failure.

Example Tool: AWS Elastic Load Balancer (ELB) integrates with AWS’s service registry for server-side discovery.

Best Practices for Implementing Service Discovery

To ensure a robust service discovery system, follow these best practices:

  • Choose the Right Model: Use client-side discovery for custom load balancing or server-side discovery for centralized routing.

  • Ensure High Availability: Deploy multiple registry instances and test failover scenarios to prevent downtime.

  • Automate Registration: Use self-registration, sidecars, or orchestration tools for dynamic environments. Ensure stale services are deregistered.

  • Use Health Checks: Monitor service health and automatically remove failing instances.

  • Follow Naming Conventions: Use clear, unique service names with versioning (e.g., payment-service-v1) to avoid conflicts.

  • Caching: Implement caching to reduce registry load and improve performance.

  • Scalability: Ensure the discovery system can handle service growth.

Conclusion

Service discovery may not be the flashiest part of a distributed system, but it’s a critical component. Think of it as the address book for your microservices architecture. Without it, scaling and maintaining distributed systems would be chaotic. By enabling seamless communication and coordination, service discovery ensures that complex applications run reliably and efficiently.

100 Days of DevOps: Day 41

2025-09-13 19:30:01

Creating and Running a Custom Apache Docker Container on App Server 3

Completing the exercise involves a sequence of steps: creating a Dockerfile, building a custom Docker image from it, and then running a container from that image. The provided log showcases the correct commands and their outputs for each stage.

Step 1: Create the Dockerfile

First, you need to create the Dockerfile with the specified requirements. The file should be named Dockerfile (with a capital D) and located at /opt/docker/Dockerfile.

  1. Navigate to the correct directory:

    cd /opt/docker
    
  2. Open the file for editing using sudo vi:

    sudo vi Dockerfile
    
  3. Add the following content to the file. This code uses ubuntu:24.04 as the base image, installs Apache2, changes the listening port to 5003, exposes the port, and starts the service.

    # Use ubuntu:24.04 as the base image
    FROM ubuntu:24.04
    
    # Install apache2
    RUN apt-get update && \
        apt-get install -y apache2
    
    # Configure Apache to listen on port 5003
    RUN sed -i 's/^Listen 80$/Listen 5003/' /etc/apache2/ports.conf
    
    # Expose port 5003
    EXPOSE 5003
    
    # Start Apache in the foreground
    CMD ["apache2ctl", "-D", "FOREGROUND"]
    

Step 2: Build the Docker Image

Once the Dockerfile is saved, you can build the image. This process reads the instructions from the Dockerfile and creates a new, reusable image.

  1. From the /opt/docker directory, use the docker build command. The -t flag tags the image with a name, and the . specifies the current directory as the build context.

    sudo docker build -t nautilus-apache .
    
  2. The output will show the build process, including downloading the base image, running each command in the Dockerfile, and finally, tagging and exporting the image. A successful build is indicated by the FINISHED status.

Step 3: Run the Docker Container

The final step is to run a container from the newly created image.

  1. Use the docker run command with the following flags:
    • -d runs the container in detached mode, so it runs in the background.
    • -p 5003:5003 maps port 5003 on the host machine to port 5003 inside the container, making the Apache server accessible.
  2. Execute the command:

    sudo docker run -d -p 5003:5003 nautilus-apache
    
  3. Upon success, the command will print a long container ID, confirming that the container is running in the background and is ready to serve requests on port 5003.

Building an App Just by Talking to AI: My Google AI Studio Multimodal Challenge

2025-09-13 19:24:25

This is a submission for the Google AI Studio Multimodal Challenge

What I Built

I built a voice assistant app to make conversations with AI more natural. It's designed for AIs without a microphone function, like Google Gemini. Instead of manual text input, users can talk directly to the AI.

The app converts spoken words into text in real-time, which can then be copied to the clipboard with one click. This makes pasting the text into any AI chat, such as Gemini, seamless and intuitive.

My project is based on a simple concept: anyone, even without programming knowledge, can use voice to interact with an AI and solve a real-world problem.

Demo

This is a short video demonstrating the app's functionality:
yuutube
GITHub HP.

How I Used Google AI Studio

This app is a story of co-creation with AI. I'm not a programmer, but this project began when I simply started a conversation with Google AI Studio, saying, "I want to build an app that can take voice input."

Initial Ideation: I explained the app's concept and the necessary functions—voice recognition, text conversion, and a copy feature—to AI Studio.

Code Generation: AI Studio understood my instructions and generated the initial HTML, CSS, and JavaScript code.

Feature Refinement: I requested further improvements from AI Studio, such as "auto-start voice recognition" and "character count display," to enhance the user experience.

This project proves that AI Studio is more than just a code generator; it's a creative partner that helps turn ideas into reality.

Multimodal Features

My app leverages "voice" as a new modality for interacting with AI.

Voice Input: Users can speak to the app instead of typing, making the interaction with AI feel more human and natural.

Extending AI Tools: My app expands the use of AI tools like Gemini by enabling them to be controlled with voice. This creates a richer user experience by combining two distinct modalities: voice input and text-based AI output.

This project is a small attempt to build a new type of "AI assistant" that combines voice and AI in a novel way. -->