Nutshell Series

gRPC in Simple Terms (Modern RPC)

gRPC is a modern way for applications to talk to each other in distributed systems. It is the latest evolution of RPC (Remote Procedure Call) designed for speed, efficiency, and scalability.

Simply put:

gRPC allows one service to call another service’s function just like calling a local method — but faster and smarter for cloud systems.

What is gRPC?

gRPC is a communication framework that helps different services exchange data efficiently.

Think of it like:

Calling a function in another computer as if it is in your own code.

It is widely used in:

  • Microservices
  • Cloud applications
  • Real-time systems
  • High-performance backend systems

How gRPC Works (Simple Flow)

  1. Developer defines service in a .proto file
  2. gRPC generates client and server code automatically
  3. Client sends request in binary format (small & fast)
  4. Communication happens using HTTP/2
  5. Server processes and sends response

Why gRPC is Faster

gRPC is fast because:

  • Uses binary data instead of JSON
  • Uses HTTP/2 instead of HTTP/1
  • Supports streaming
  • Uses strong contracts

This makes it ideal for internal service communication.

Types of gRPC Communication

  • Unary → One request → One response
  • Server Streaming → One request → Many responses
  • Client Streaming → Many requests → One response
  • Bidirectional Streaming → Many ↔ Many

This is useful for:

  • Live tracking apps
  • Chat systems
  • Financial streaming data
  • IoT systems

gRPC vs REST

Feature gRPC REST
Speed Very Fast Medium
Data Format Binary JSON
Streaming Yes Limited
Best For Internal Microservices Public APIs
Human Readable No Yes

Advantages of gRPC

  • Very high performance
  • Small payload size
  • Strong typing reduces runtime errors
  • Built for microservices
  • Supports real-time streaming

Challenges

  • Harder to debug compared to REST
  • Not directly supported in browsers
  • Requires learning Protocol Buffers

Simple Real-World Example

Imagine an e-commerce system:

  • Order Service calls Payment Service → gRPC
  • Website calls Backend API → REST

This provides:

  • Fast internal communication
  • Simple external integration

Conclusion

gRPC is the modern evolution of RPC, designed for cloud-native and microservices architectures. It helps systems communicate faster, more efficiently, and at large scale.

As distributed systems continue to grow, gRPC is becoming a standard choice for internal service communication.

Nutshell Series

Cold vs Hot Observables in Rx.NET

Reactive Extensions (Rx.NET) is used to handle asynchronous data streams in .NET applications.
One of the most important concepts to understand is the difference between Cold Observables and Hot Observables.


What is an Observable?

An Observable is a data stream that we can subscribe to and receive values over time.

IObservable<int> stream = Observable.Range(1, 3);
stream.Subscribe(x => Console.WriteLine(x));

Cold Observables (Simple Meaning)

  • Starts only when someone subscribes
  • Each subscriber gets separate execution
  • Default behavior in Rx.NET
  • Best used for API calls, database queries, file reading

Simple Cold Observable Example

var cold = Observable.Range(1, 3);

cold.Subscribe(x => Console.WriteLine("Subscriber 1: " + x));
cold.Subscribe(x => Console.WriteLine("Subscriber 2: " + x));

Here execution happens twice because each subscriber gets a new stream.


Hot Observables (Simple Meaning)

  • Runs continuously and shares data
  • All subscribers receive the same live stream
  • Execution happens only once
  • Best used for event streams, real-time systems, UI events

Simple Hot Observable Example

var hot = Observable.Interval(TimeSpan.FromSeconds(1))
                    .Publish()
                    .RefCount();

hot.Subscribe(x => Console.WriteLine("Subscriber 1: " + x));
hot.Subscribe(x => Console.WriteLine("Subscriber 2: " + x));

Now both subscribers share the same execution.


Even Simpler Way Using Share()

var hot = Observable.Interval(TimeSpan.FromSeconds(1))
                    .Share();

Share() is a shortcut for Publish().RefCount().


Real Life Example

  • Cold Observable: Watching a recorded video separately
  • Hot Observable: Watching live TV broadcast

Cold vs Hot Comparison

Feature Cold Hot
Execution Per subscriber Shared
Data Type Fresh data Live data
Performance Lower Higher
Use Case API / Database Streaming

Best Practices

  • Use Cold Observables for request-based operations
  • Use Hot Observables for real-time streaming
  • Share expensive operations to avoid duplicate execution

Conclusion

Understanding Cold vs Hot Observables is essential for building scalable reactive applications.
Choosing the correct type helps avoid duplicate processing and improves system performance.

Technology: Rx.NET | Reactive Programming

Nutshell Series

Fixing “Value cannot be null. (Parameter ‘provider’)” Error While Running Azure Function Apps Locally

While developing Azure Function Apps locally, you may encounter the runtime error:

Value cannot be null. (Parameter 'provider')

This issue can be frustrating because it appears during startup and often looks like a coding problem. However, in most cases, it is caused by local tooling or runtime installation issues.

🚨 Problem

When running the Function App locally using:

func start

The runtime fails with:

Value cannot be null. (Parameter 'provider')

This typically happens:

  • After updating SDKs or runtime
  • When Azure Functions Core Tools is outdated or corrupted
  • After switching runtime models (in-process → isolated)
  • When dependencies are partially installed
  • After environment setup changes

🔍 Root Cause

This error is generally caused by:

  • Broken or outdated Azure Functions Core Tools installation
  • Runtime dependency mismatch
  • Corrupted local function runtime cache
  • Improper SDK/runtime configuration

Essentially, the Azure Functions runtime fails to initialize its internal service provider. This is a tooling/runtime problem — not your application code.

✅ Recommended Fix — Reinstall Azure Functions Local Runtime

The most reliable fix is to completely reinstall Azure Functions Core Tools and local runtime components.

Follow official Microsoft guide:


Run Azure Functions locally – Microsoft Docs

🧹 Step 1 — Remove Existing Installation

If installed via npm:

npm uninstall -g azure-functions-core-tools

If installed via MSI:

  • Go to Control Panel → Programs & Features
  • Remove Azure Functions Core Tools
  • Restart your system

📦 Step 2 — Install Latest Version

npm install -g azure-functions-core-tools@4 --unsafe-perm true

This ensures:

  • Correct runtime initialization
  • Updated dependency providers
  • Compatibility with latest Azure Functions SDK

🔄 Step 3 — Clean Local Function Cache

Delete these folders if present:

.azurefunctions
bin
obj

Then rebuild:

dotnet build
func start

📌 Additional Troubleshooting

  • Ensure correct .NET SDK version is installed
  • Verify isolated vs in-process configuration
  • Check Functions Core Tools version:
func --version
  • Update Azure Functions VS Code extension
  • Clear NuGet cache:
dotnet nuget locals all --clear

🧠 Key Takeaway

Most “Value cannot be null. (provider)” errors occur due to:

  • Broken local runtime installation
  • Outdated Azure Functions Core Tools

Reinstalling the runtime is often the fastest and most reliable fix.

🚀 Conclusion

If your Function App fails locally with provider null error:

  • Do not debug business logic first
  • Fix local runtime environment
  • Reinstall using official Microsoft guidance

This approach can save hours of debugging and restore local execution immediately.

Nutshell Series

Azure Blob Storage Tiers Explained: Hot, Cool, Cold, Archive, and Premium

Azure Blob Storage offers multiple storage tiers that allow you to store data in a cost-effective way
based on how frequently the data is accessed and how quickly it needs to be retrieved.
Choosing the right tier helps balance performance, availability, and cost.

Azure Storage Performance Tiers

Azure Blob Storage provides two performance tiers:

  • Premium performance tier
  • Standard performance tier

Premium Storage Tier

Premium storage is optimized for mission-critical and high-performance applications.
It provides low latency and high throughput.

  • Currently available only for Block Blob storage
  • Uses SSD-based storage
  • Designed for workloads requiring consistent low latency
  • Higher cost compared to standard tiers

Standard Storage Access Tiers

The Standard performance tier (available with GPv2 storage accounts) supports multiple access tiers
that are optimized for different data access patterns.

Hot Storage Tier

Hot storage is optimized for data that is accessed frequently.

  • Lowest access costs
  • Higher storage costs compared to other standard tiers
  • Best for active data and frequently accessed objects
  • Highest availability SLA among standard tiers

Cool Storage Tier

Cool storage is optimized for data that is accessed infrequently and stored for at least 30 days.

  • Lower storage costs than Hot tier
  • Higher access costs compared to Hot tier
  • Slightly lower availability SLA than Hot tier
  • Ideal for short-term backups and disaster recovery data

Cold Storage Tier (New)

Cold storage is designed for data that is rarely accessed but still needs to remain online.
It provides a lower-cost option than Cool storage while maintaining online accessibility.

  • Lower storage costs than Cool tier
  • Higher access costs than Cool tier
  • Minimum storage duration of 90 days
  • Data remains online and accessible without rehydration
  • Ideal for long-term retention data accessed occasionally

Archive Storage Tier

Archive storage is optimized for data that is rarely accessed and stored for long periods.
It provides the lowest storage cost but with higher access latency.

  • Lowest storage cost of all tiers
  • Data is stored offline
  • Highest data access costs
  • Minimum storage duration of 180 days
  • Data retrieval requires rehydration and can take hours

Storage Tier Scope and Limitations

  • The Hot and Cool tiers can be set at the storage account level.
  • The Archive tier cannot be set at the account level.
  • Hot, Cool, Cold, and Archive tiers can be set at the blob (object) level.
  • The Archive tier is available only at the blob level.

Key Considerations When Choosing a Tier

  • Hot tier prioritizes performance and availability.
  • Cool tier trades slightly lower availability and higher access cost for lower storage cost.
  • Cold tier provides lower storage cost while keeping data online.
  • Archive tier minimizes storage cost but requires rehydration and higher access latency.

Summary

  • Premium – High-performance workloads requiring low latency.
  • Hot – Frequently accessed data.
  • Cool – Infrequently accessed data stored for at least 30 days.
  • Cold – Rarely accessed data stored for at least 90 days.
  • Archive – Long-term data stored for at least 180 days with flexible access latency.

By selecting the appropriate storage tier, organizations can significantly reduce costs
while meeting performance and availability requirements.

Nutshell Series

Azure Blob Storage: Block, Append, and Page Blobs Explained

Azure Blob Storage provides three types of blobs designed for different workloads:
Block Blobs, Append Blobs, and Page Blobs.
Each blob type is optimized for specific data access patterns and storage requirements.

Block Blobs

Block blobs are designed for efficient upload and storage of large amounts of unstructured data such as documents, images, videos, and backups.

  • Data is stored as blocks identified by unique block IDs.
  • Blocks are uploaded independently and committed together to create or update a blob.
  • Supports up to 50,000 blocks.
  • Modern service versions support block sizes up to 4,000 MiB (≈4 GB).
  • Maximum block blob size can exceed 190 TiB.
  • Smaller block blobs can be uploaded using a single write operation.

Legacy Limits (Older REST Versions)

  • Maximum block size: 100 MB
  • Maximum blob size: approximately 4.75 TB
  • Older REST versions supported 4 MB blocks with a maximum size of around 195 GB

Page Blobs

Page blobs are optimized for random read and write operations and are similar to disk storage.
They are commonly used for virtual machine disks.

  • Data is stored in 512-byte pages.
  • Supports random access using offset and range aligned to 512-byte boundaries.
  • Writes occur in-place and are immediately committed.
  • Individual pages or multiple pages (up to 4 MB) can be updated at once.
  • Maximum page blob size is 8 TiB.

Append Blobs

Append blobs are optimized for scenarios where data is continuously added to the end of a blob, such as logging and auditing.

  • Built using blocks but support append-only operations.
  • Existing blocks cannot be modified or deleted.
  • Block IDs are not exposed.
  • Each block can be up to 4 MB.
  • Supports up to 50,000 blocks.
  • Maximum append blob size is approximately 195 GB.

Choosing the Right Blob Type

  • Block Blob – Files, media, backups, and general storage.
  • Append Blob – Logs, telemetry, and audit trails.
  • Page Blob – VM disks and random read/write workloads.

How the Blob Type Is Specified

The blob type must be specified at the time of creation and cannot be changed later.
Applications, SDKs, CLI tools, or Azure services explicitly define the blob type.

Using REST API

x-ms-blob-type: BlockBlob | AppendBlob | PageBlob

Using Azure CLI

Azure CLI allows you to specify the blob type when creating or uploading a blob.

Create a Block Blob (default)

az storage blob upload \
  --account-name mystorageaccount \
  --container-name data \
  --name file.txt \
  --file file.txt

Create an Append Blob

az storage blob create \
  --account-name mystorageaccount \
  --container-name logs \
  --name app.log \
  --type append

Create a Page Blob

az storage blob create \
  --account-name mystorageaccount \
  --container-name vhds \
  --name disk.vhd \
  --type page \
  --size 1073741824

The --type parameter explicitly defines whether the blob is created as a block, append, or page blob.

Summary

  • Block blobs provide scalable storage for large unstructured data.
  • Append blobs are optimized for append-only workloads like logging.
  • Page blobs provide disk-like storage with random read/write access.
  • The blob type must be specified during creation using APIs, SDKs, or CLI.

Choosing the correct blob type ensures optimal performance, scalability, and cost efficiency in Azure Storage solutions.

Nutshell Series

Types of Telecommunications Networks Explained

Telecommunications networks enable communication over distances by connecting devices and systems.
Based on coverage and purpose, they are classified into different types.

1. Public Switched Telephone Network (PSTN)

  • Traditional network for voice communication
  • Uses circuit switching
  • Mainly supports landline calls
  • Managed by telecom providers

2. Local Area Network (LAN)

  • Covers small areas like homes or offices
  • High-speed data transfer
  • Privately owned and managed
  • Uses Ethernet or Wi-Fi

3. Wide Area Network (WAN)

  • Spans large geographic areas
  • Connects multiple LANs
  • Uses leased lines, fiber, or satellite
  • Common in enterprise networks

4. Internet

  • Global network of networks
  • Uses TCP/IP protocols
  • Supports web, email, cloud, and streaming
  • Publicly accessible worldwide

Each type of telecommunications network plays a vital role, from local connectivity to global communication.

Nutshell Series

Git Force Push: Do’s & Don’ts (Quick Guide)

Force push (git push --force) overwrites the remote branch to match your local branch, even if it rewrites commit history.

✅ Do

  • Prefer --force-with-lease (safer than --force):
git fetch origin
git push --force-with-lease origin my-branch
  • Force-push only your feature branches (e.g., feature/*, bugfix/*).
  • Create a backup branch/tag first (easy rollback):
git fetch origin
git branch backup/my-branch origin/my-branch
# or: git tag backup-my-branch origin/my-branch
  • Warn teammates if anyone else might be using the branch.

❌ Don’t

  • Don’t force-push to main/master or release/* (breaks traceability and can disrupt CI/CD).
  • Don’t use --force blindly (can overwrite someone else’s commits).
  • Don’t rewrite shared history after others have pulled and started work.
  • Don’t “fix conflicts” by deleting remote work via force push.

Safe Pattern (Copy/Paste)

git checkout my-branch
git fetch origin
git branch backup/my-branch origin/my-branch
git rebase origin/main
git push --force-with-lease origin my-branch

Rule of thumb: If the branch is shared or protected, avoid force push. If it’s your feature branch, use --force-with-lease and back it up first.

Nutshell Series

Azure DevOps Directory Variables

Azure DevOps pipelines provide predefined variables to reference paths, workspaces, and directories consistently. Here’s a simplified two-column version for better mobile responsiveness:

Variable Description & Example Paths
$(Build.SourcesDirectory) Sources folder where repository code is checked out.

Linux: /home/vsts/work/1/s

Windows: C:\agent\_work\1\s

$(Build.ArtifactStagingDirectory) Folder used for staging build artifacts before publishing.

Linux: /home/vsts/work/1/a

Windows: C:\agent\_work\1\a

$(Build.BinariesDirectory) Folder where intermediate build outputs and binaries are placed.

Linux: /home/vsts/work/1/b

Windows: C:\agent\_work\1\b

$(Pipeline.Workspace) Root workspace directory for the pipeline run.

Linux: /home/vsts/work/1/

Windows: C:\agent\_work\1\

$(Agent.ToolsDirectory) Folder where agent stores cached tools and SDKs.

Linux: /home/vsts/work/1/c

Windows: C:\agent\_work\1\c

$(Agent.TempDirectory) Temporary folder used during pipeline execution.

Linux: /home/vsts/work/_temp

Windows: C:\agent\_work\_temp

$(Build.Repository.LocalPath) Local path where repository content is downloaded.

Linux: /home/vsts/work/1/s

Windows: C:\agent\_work\1\s

$(Agent.WorkFolder) Agent’s root work folder that contains all pipeline runs.

Linux: /home/vsts/work

Windows: C:\agent\_work

$(Agent.BuildDirectory) Build-specific directory (same as workspace root).

Linux: /home/vsts/work/1/

Windows: C:\agent\_work\1\

$(Agent.HomeDirectory) Directory where agent software is installed.

Linux: /home/vsts/agent

Windows: C:\agent

Reference: Azure DevOps Predefined Build Variables

Nutshell Series

Commonly Confused English Words Every Tech Professional Should Know

Communication in tech isn’t just about code — it’s also about clarity. Whether you’re writing documentation, naming variables, or emailing clients, using the right words can change how your message is understood. Many professionals, especially those who use English as a second language, find it challenging to distinguish between words that sound similar but mean completely different things.

This guide lists the most commonly confused English word pairs — like principal vs. principle — and explains why understanding their real meanings is crucial for global tech professionals who want to excel in their roles and communicate effectively.


Why It Matters for Non-Native English-Speaking Tech Professionals

  • Better Documentation: Precise language makes your technical documentation, code comments, and API references clearer for everyone.
  • Professional Communication: Emails, reports, and design proposals reflect your professionalism. The right word choice shows confidence and attention to detail.
  • Fewer Misunderstandings: In global teams, small differences in words can lead to big misunderstandings. Clarity ensures smooth collaboration.
  • Improved Code Clarity: Developers often use English for variable names, commit messages, and documentation. Knowing the difference between words like affect and effect makes your work more readable and precise.

Commonly Confused Word Pairs (and How to Remember Them)

Word Pair Meaning 1 Meaning 2 Example
Principal vs Principle Principal → Main or head of a school/project. Principle → Moral rule or belief. The principal engineer followed ethical principles.
Personal vs Personnel Personal → Private or individual. Personnel → Staff or employees. Keep your personal files separate from company personnel data.
Affect vs Effect Affect → To influence (verb). Effect → The result (noun). The outage affected performance; the effect was downtime.
Compliment vs Complement Compliment → Praise or kind remark. Complement → To complete or enhance. The UI design complements the backend logic — that’s a compliment to the dev team!
Stationary vs Stationery Stationary → Not moving. Stationery → Writing materials. The server rack is stationary, not stationery.
Assure vs Ensure vs Insure Assure → To make someone certain. Ensure → To make sure something happens.
Insure → To protect financially.
I assure you this patch will ensure stability and insure against data loss.
Discreet vs Discrete Discreet → Careful and tactful. Discrete → Separate or distinct. The system has discrete modules; be discreet with access logs.
Elicit vs Illicit Elicit → To draw out or evoke. Illicit → Illegal or forbidden. The test elicited a bug — not an illicit action!
Accept vs Except Accept → To receive or agree. Except → Excluding. We accept all pull requests except untested ones.
Advice vs Advise Advice → Suggestion (noun). Advise → To give advice (verb). Thanks for your advice; I’ll advise the team accordingly.
Imply vs Infer Imply → To suggest indirectly. Infer → To conclude from evidence. The tester implied the issue was fixed; we inferred it was safe to deploy.
Lose vs Loose Lose → To misplace or fail to win. Loose → Not tight or free. Don’t lose the config file or leave the cable loose.
Proceed vs Precede Proceed → To continue or move forward. Precede → To come before. Testing should proceed after deployment notes that precede it.

Tips to Remember

  • Say It Aloud: Similar-sounding words often differ in stress or rhythm — practice pronunciation to internalize differences.
  • Visualize Meaning: Picture the scenario where the word fits; for example, “stationery” brings pens and paper to mind.
  • Use in Code Comments: Practice correct usage when writing commit messages, documentation, or naming variables.
  • Keep a Mini Dictionary: Note down any confusing word pairs you encounter while reading technical blogs or documentation.

Being a great tech professional isn’t only about mastering frameworks and algorithms — it’s also about communicating precisely. For non-native English-speaking professionals, developing language accuracy builds confidence, improves collaboration, and strengthens your professional identity. Remember, the right word not only expresses your thoughts — it defines your clarity as a communicator and your excellence as an engineer.


Written for global tech professionals who believe that clarity in language is as essential as clarity in code.

Nutshell Series

🧩 Modern C# Operators and Syntax Cheatsheet (C# 6–12 & Beyond)

C# has evolved tremendously — from a verbose OOP language into a sleek, expressive, and modern programming language.
With each version, Microsoft introduced powerful operators that make code safer, more concise, and easier to read.
Here’s your ultimate guide to all the important operators you should know in modern C#.


🔹 1. Null-Coalescing & Safe Navigation

These operators help you handle null values gracefully without throwing exceptions.

Operator Example Description
?? var name = input ?? "Unknown"; Returns the right-hand value if the left-hand is null.
??= name ??= "Default"; Assigns a value only if the variable is null.
?. var len = person?.Name?.Length; Safely navigates through objects that may be null.
?[] var ch = text?[0]; Safely index into arrays or lists.
! obj!.ToString() Null-forgiving operator — tells the compiler “I know this isn’t null.”
is null / is not null if (value is null) Type-safe null comparison syntax.

🔹 2. Pattern Matching (C# 8–12)

Pattern matching enables powerful, declarative logic without repetitive if/else chains.

Pattern Example Description
is if (x is int i) Checks type and assigns if match succeeds.
is not if (obj is not string) Negated type match.
switch expression var area = shape switch { Circle c => c.Radius, Rectangle r => r.Width, _ => 0 }; Expression-based switch replacement.
Property pattern if (person is { Age: > 18, Name: not null }) Matches properties directly.
Tuple pattern (x, y) switch { (0, 0) => "Origin", (_, 0) => "X-axis" } Match multiple values together.
Relational pattern if (n is > 0 and < 10) Match numeric or range conditions.
List pattern (C# 11+) if (nums is [1, 2, .. var rest]) Match array/list structure.
Slice pattern if (arr is [1, .. var middle, 10]) Match prefix and suffix with ...

🔹 3. Expression & Lambda Enhancements

These operators make your code more concise and expressive.

Operator Example Description
=> public int Add(int x, int y) => x + y; Expression-bodied members.
() => () => DoWork() Lambda expression syntax.
_ _ = DoSomething(); Discard or wildcard variable.

🔹 4. Assignment & Arithmetic Shortcuts

Operator Example Description
+=, -=, *=, /=, %= x += 5; Compound assignments.
++ / -- count++; Increment or decrement.
<<, >>, >>> uint n = a >>> 1; Bit shift operators; >>> is unsigned right shift (C# 11).

🔹 5. Range & Index Operators (C# 8+)

Operator Example Description
^ var last = arr[^1]; Index from the end (1 = last element).
.. var sub = arr[1..4]; Slice between start and end indexes.
..^ arr[1..^1] Slice excluding first and last.

🔹 6. Type and Reflection Helpers

Operator Example Description
as obj as string Safe type cast, returns null if fails.
is if (obj is MyType) Checks runtime type.
typeof typeof(string) Gets type info at compile time.
nameof nameof(MyProperty) Gets identifier name as string.
default default(int) Returns default value of a type.

🔹 7. New Features in C# 12 / 13

Feature Example Description
Primary constructors class Person(string Name, int Age) Compact way to declare constructor + properties.
Collection expressions var list = [1, 2, 3]; Simpler syntax for new List<int> { 1, 2, 3 }.
Inline arrays Span<int> span = [1, 2, 3]; Allocate arrays inline without new.
Default lambda parameters (int x = 0) => x * 2 Lambdas with default argument values.
Params collections (C# 13) void Log(params string[] msgs) Flexible params syntax with collections.

💡 Quick Example


string? input = "";
string name = input ?? "Guest";      // null-coalescing
name ??= "Anonymous";                // assign if null

var len = name?.Length ?? 0;         // null-safe access
if (name is { Length: > 5 }) { }     // property pattern

var arr = [1, 2, 3, 4, 5];
var slice = arr[1..^1];              // [2,3,4]

var point = (x: 0, y: 0);
var message = point switch
{
    (0, 0) => "Origin",
    (_, 0) => "X-axis",
    _ => "Other"
};

Modern C# syntax lets you write expressive, safe, and elegant code with minimal boilerplate.
If you’re upgrading from older C# versions, take time to learn the ??, ?.,
pattern matching, and range operators — they’ll make your code cleaner and far more readable.

Stay updated with C# 13 and .NET 9 releases, as the language continues evolving toward simplicity and power!